From a258a8693f664d4fe93f36279dbeec1ae80e3389 Mon Sep 17 00:00:00 2001 From: liuyuanmu Date: Thu, 21 Nov 2019 10:27:13 +0800 Subject: [PATCH 1/8] fix DataVersionConflictException bug --- .../bftsmart/service/BftsmartNodeServer.java | 4 --- .../core/TransactionBatchProcessor.java | 5 ++-- .../core/TransactionBatchProcessorTest.java | 29 +++++-------------- .../ledger/DataVersionConflictException.java | 2 +- 4 files changed, 10 insertions(+), 30 deletions(-) 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..e3eddc68 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 @@ -410,10 +410,6 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer } 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; } } 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..e347f101 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 @@ -273,9 +273,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 +292,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/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 06bf987d..6a1b6ed8 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 @@ -365,17 +365,16 @@ public class TransactionBatchProcessorTest { txbatchProcessor.schedule(txreq5); // 预期会产生版本冲突异常; DataVersionConflictionException; - DataVersionConflictException versionConflictionException = null; - try { - txbatchProcessor.schedule(txreq6); - } catch (DataVersionConflictException e) { - versionConflictionException = e; - } - assertNotNull(versionConflictionException); + TransactionResponse resp = txbatchProcessor.schedule(txreq6); + assertFalse(resp.isSuccess()); + // 提交新区块 newBlock = newBlockEditor.prepare(); newBlockEditor.commit(); + // 预期区块高度为3 + assertEquals(3, ledgerRepo.getLatestBlockHeight()); + BytesValue v1 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getBytes("K1"); v3 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getBytes("K3"); @@ -383,7 +382,7 @@ public class TransactionBatchProcessorTest { long k1_version = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()) .getDataVersion("K1"); assertEquals(1, k1_version); - + // K3 的版本增1 long k3_version = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()) .getDataVersion("K3"); assertEquals(1, k3_version); @@ -393,20 +392,6 @@ public class TransactionBatchProcessorTest { assertEquals("V-1-2", v1.getValue().toUTF8String()); assertEquals("V-3-2", v3.getValue().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.getTransactionContent().getHash()); -// -// assertNotNull(tx1); -// assertEquals(TransactionState.SUCCESS, tx1.getExecutionState()); - } private HashDigest initLedger(MemoryKVStorage storage, BlockchainKeypair... partiKeys) { 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; From 85ac5d23368ec5a7cb56f992d7b96d4cfa22f431 Mon Sep 17 00:00:00 2001 From: zhangshuang Date: Mon, 25 Nov 2019 11:37:52 +0800 Subject: [PATCH 2/8] solve transaction and block rollback exception! --- .../bftsmart/service/BftsmartNodeServer.java | 48 +++++--- .../core/LedgerTransactionalEditor.java | 6 +- .../test/SDK_GateWay_Tx_RollBack_Test_.java | 114 ++++++++++++++++++ .../service/utils/MemoryKVStorage.java | 5 + .../jd/blockchain/intgr/IntegrationBase.java | 30 +++++ .../intgr/IntegrationBlockFullRollback.java | 105 ++++++++++++++++ 6 files changed, 291 insertions(+), 17 deletions(-) create mode 100644 source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Tx_RollBack_Test_.java create mode 100644 source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBlockFullRollback.java 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 e3eddc68..bbecdb5c 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 @@ -402,16 +402,15 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer boolean isOK = true; TransactionState transactionState = TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK; - for (int i = 0; i < commands.length; i++) { - byte[] txContent = commands[i]; - try { + try { + for (int i = 0; i < commands.length; i++) { + byte[] txContent = commands[i]; AsyncFuture asyncFuture = messageHandle.processOrdered(msgId++, txContent, realmName, batchId); asyncFutureLinkedList.add(asyncFuture); - } catch (BlockRollbackException e) { + } + } catch (BlockRollbackException e) { LOGGER.error("Error occurred while processing ordered messages! --" + e.getMessage(), e); isOK = false; - break; - } } if (isOK) { @@ -448,22 +447,21 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer } } + // Block full rollback responses, generated in pre compute phase, due to tx fail public 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 - * - */ - public List updateAppResponses(List asyncResponseLinkedList) { + + + //Pre compute block hash values are inconsistent, update batch messages to new state + public List preCompInconsistentAppResps(List asyncResponseLinkedList) { List updatedResponses = new ArrayList<>(); for(int i = 0; i < asyncResponseLinkedList.size(); i++) { @@ -476,15 +474,33 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer return updatedResponses; } + + //Consensus accept phase will terminate, pre compute commit exception occurs, update batch messages execute state to block full rollback + public List blockRollbackAppResps(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_BLOCK_FULL_ROLLBACK); + updatedResponses.add(BinaryProtocol.encode(resp, TransactionResponse.class)); + } + + return updatedResponses; + } + /** * * Decision has been made at the consensus stage, commit block * */ 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; + } } /** 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/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Tx_RollBack_Test_.java b/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Tx_RollBack_Test_.java new file mode 100644 index 00000000..4c8c233b --- /dev/null +++ b/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Tx_RollBack_Test_.java @@ -0,0 +1,114 @@ +package test.com.jd.blockchain.sdk.test; + +import com.jd.blockchain.binaryproto.DataContractRegistry; +import com.jd.blockchain.crypto.*; +import com.jd.blockchain.ledger.*; +import com.jd.blockchain.sdk.BlockchainService; +import com.jd.blockchain.sdk.client.GatewayServiceFactory; +import com.jd.blockchain.transaction.TxResponseMessage; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +//Transaction rollback test example +public class SDK_GateWay_Tx_RollBack_Test_ { + + private PrivKey privKey; + private PubKey pubKey; + + private BlockchainKeypair CLIENT_CERT = null; + + private String GATEWAY_IPADDR = null; + + private int GATEWAY_PORT; + + private boolean SECURE; + + private BlockchainService service; + + private BlockchainKeypair user; + + private BlockchainKeypair dataAccount; + + @Before + public void init() { + + privKey = SDK_GateWay_KeyPair_Para.privkey1; + pubKey = SDK_GateWay_KeyPair_Para.pubKey1; + + CLIENT_CERT = new BlockchainKeypair(SDK_GateWay_KeyPair_Para.pubKey0, SDK_GateWay_KeyPair_Para.privkey0); + GATEWAY_IPADDR = "127.0.0.1"; + GATEWAY_PORT = 11000; + SECURE = false; + GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IPADDR, GATEWAY_PORT, SECURE, + CLIENT_CERT); + service = serviceFactory.getBlockchainService(); + + DataContractRegistry.register(TransactionContent.class); + DataContractRegistry.register(TransactionContentBody.class); + DataContractRegistry.register(TransactionRequest.class); + DataContractRegistry.register(NodeRequest.class); + DataContractRegistry.register(EndpointRequest.class); + DataContractRegistry.register(TransactionResponse.class); + + user = BlockchainKeyGenerator.getInstance().generate(); + + dataAccount = BlockchainKeyGenerator.getInstance().generate(); + + } + + @Test + public void failedTxRollback_Test() { + + HashDigest[] ledgerHashs = service.getLedgerHashs(); + + //Construct the first transaction + TransactionTemplate txTemp = service.newTransaction(ledgerHashs[0]); + + AsymmetricKeypair keyPair = new BlockchainKeypair(pubKey, privKey); + + //Register user account + txTemp.users().register(user.getIdentity()); + + //Register data account + txTemp.dataAccounts().register(dataAccount.getIdentity()); + + String dataKey = "jd_code"; + String dataVal = "www.jd.com"; + + // Construct error kv version + txTemp.dataAccount(dataAccount.getAddress()).setText(dataKey, dataVal, 1); + + PreparedTransaction prepTx = txTemp.prepare(); + + prepTx.sign(keyPair); + + //Commit transaction + TransactionResponse transactionResponse = prepTx.commit(); + + //The first transaction will rollback, due to version error + assertEquals(transactionResponse.getExecutionState().CODE, TransactionState.DATA_VERSION_CONFLICT.CODE); + + //Construct the second transaction + TransactionTemplate txTemp1 = service.newTransaction(ledgerHashs[0]); + + txTemp1.users().register(user.getIdentity()); + + txTemp1.dataAccounts().register(dataAccount.getIdentity()); + + txTemp1.dataAccount(dataAccount.getAddress()).setText(dataKey, dataVal, -1); + + PreparedTransaction prepTx1 = txTemp1.prepare(); + + prepTx1.sign(keyPair); + + TransactionResponse transactionResponse1 = prepTx1.commit(); + + //The second transaction success + assertTrue(transactionResponse1.isSuccess()); + + } + +} diff --git a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/MemoryKVStorage.java b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/MemoryKVStorage.java index 0c2192a3..1cb202fa 100644 --- a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/MemoryKVStorage.java +++ b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/MemoryKVStorage.java @@ -12,6 +12,8 @@ import com.jd.blockchain.utils.io.BytesMap; public class MemoryKVStorage implements ExPolicyKVStorage, VersioningKVStorage, KVStorageService, BytesMap { + public static boolean isBlockFullRollbackTest = false; + private ExistancePolicyKVStorageMap exStorage = new ExistancePolicyKVStorageMap(); private VersioningKVStorageMap verStorage = new VersioningKVStorageMap(); @@ -32,6 +34,9 @@ public class MemoryKVStorage implements ExPolicyKVStorage, VersioningKVStorage, @Override public long set(Bytes key, byte[] value, long version) { + if (isBlockFullRollbackTest) { + return -1; + } return verStorage.set(key, value, version); } 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 9c3b3320..19429524 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/IntegrationBlockFullRollback.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBlockFullRollback.java new file mode 100644 index 00000000..b3a68c77 --- /dev/null +++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBlockFullRollback.java @@ -0,0 +1,105 @@ +package test.com.jd.blockchain.intgr; + +import com.jd.blockchain.crypto.*; +import com.jd.blockchain.gateway.GatewayConfigProperties; +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.DbConnectionFactory; +import com.jd.blockchain.storage.service.utils.MemoryKVStorage; +import com.jd.blockchain.tools.initializer.LedgerBindingConfig; +import com.jd.blockchain.utils.concurrent.ThreadInvoker; +import org.junit.Test; +import test.com.jd.blockchain.intgr.initializer.LedgerInitializeTest; +import test.com.jd.blockchain.intgr.initializer.LedgerInitializeWeb4Nodes; + +import static test.com.jd.blockchain.intgr.IntegrationBase.*; + +public class IntegrationBlockFullRollback { + + private static final String DB_TYPE_MEM = "mem"; + + @Test + public void test4Memory() { + test(LedgerInitConsensusConfig.bftsmartProvider, DB_TYPE_MEM, LedgerInitConsensusConfig.memConnectionStrings); + } + + public void test(String[] providers, String dbType, String[] dbConnections) { + + // 内存账本初始化 + HashDigest ledgerHash = initLedger(dbConnections); + + // 启动Peer节点 + PeerTestRunner[] peerNodes = peerNodeStart(ledgerHash, dbType); + + DbConnectionFactory dbConnectionFactory0 = peerNodes[0].getDBConnectionFactory(); + DbConnectionFactory dbConnectionFactory1 = peerNodes[1].getDBConnectionFactory(); + DbConnectionFactory dbConnectionFactory2 = peerNodes[2].getDBConnectionFactory(); + DbConnectionFactory dbConnectionFactory3 = peerNodes[3].getDBConnectionFactory(); + + String encodedBase58Pwd = KeyGenUtils.encodePasswordAsBase58(LedgerInitializeTest.PASSWORD); + + GatewayConfigProperties.KeyPairConfig gwkey0 = new GatewayConfigProperties.KeyPairConfig(); + gwkey0.setPubKeyValue(IntegrationBase.PUB_KEYS[0]); + gwkey0.setPrivKeyValue(IntegrationBase.PRIV_KEYS[0]); + gwkey0.setPrivKeyPassword(encodedBase58Pwd); + GatewayTestRunner gateway = new GatewayTestRunner("127.0.0.1", 11000, gwkey0, + peerNodes[0].getServiceAddress(), providers,null); + + ThreadInvoker.AsyncCallback gwStarting = gateway.start(); + + gwStarting.waitReturn(); + + // 执行测试用例之前,校验每个节点的一致性; + LedgerQuery[] ledgers = buildLedgers(new LedgerBindingConfig[]{ + peerNodes[0].getLedgerBindingConfig(), + peerNodes[1].getLedgerBindingConfig(), + peerNodes[2].getLedgerBindingConfig(), + peerNodes[3].getLedgerBindingConfig(), + }, + new DbConnectionFactory[]{ + dbConnectionFactory0, + dbConnectionFactory1, + dbConnectionFactory2, + dbConnectionFactory3}); + + IntegrationBase.testConsistencyAmongNodes(ledgers); + + LedgerQuery ledgerRepository = ledgers[0]; + + GatewayServiceFactory gwsrvFact = GatewayServiceFactory.connect(gateway.getServiceAddress()); + + PrivKey privkey0 = KeyGenUtils.decodePrivKeyWithRawPassword(IntegrationBase.PRIV_KEYS[0], IntegrationBase.PASSWORD); + + PubKey pubKey0 = KeyGenUtils.decodePubKey(IntegrationBase.PUB_KEYS[0]); + + AsymmetricKeypair adminKey = new AsymmetricKeypair(pubKey0, privkey0); + + BlockchainService blockchainService = gwsrvFact.getBlockchainService(); + + //Block commit will be fail, due to storage error + MemoryKVStorage.isBlockFullRollbackTest = true; + + IntegrationBase.KeyPairResponse userResponse = IntegrationBase.testSDK_BlockFullRollBack(adminKey, ledgerHash, blockchainService); + + //Block commit will be normal + MemoryKVStorage.isBlockFullRollbackTest = false; + + IntegrationBase.KeyPairResponse userResponse1 = IntegrationBase.testSDK_RegisterUser(adminKey, ledgerHash, blockchainService); + + try { + System.out.println("----------------- Init Completed -----------------"); + Thread.sleep(Integer.MAX_VALUE); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + IntegrationBase.testConsistencyAmongNodes(ledgers); + } + private HashDigest initLedger(String[] dbConnections) { + LedgerInitializeWeb4Nodes ledgerInit = new LedgerInitializeWeb4Nodes(); + HashDigest ledgerHash = ledgerInit.testInitWith4Nodes(LedgerInitConsensusConfig.bftsmartConfig, dbConnections); + System.out.printf("LedgerHash = %s \r\n", ledgerHash.toBase58()); + return ledgerHash; + } +} From 21d8f250308bfc5e730b4771af1cd7581bed3774 Mon Sep 17 00:00:00 2001 From: zhangshuang Date: Wed, 27 Nov 2019 16:56:05 +0800 Subject: [PATCH 3/8] add mockito test for block rollback --- .../ledger/core/BlockFullRollBackTest.java | 272 ++++++++++++++++++ .../service/utils/MemoryKVStorage.java | 5 - .../intgr/IntegrationBlockFullRollback.java | 105 ------- 3 files changed, 272 insertions(+), 110 deletions(-) create mode 100644 source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/BlockFullRollBackTest.java delete mode 100644 source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBlockFullRollback.java 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..a974844a --- /dev/null +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/BlockFullRollBackTest.java @@ -0,0 +1,272 @@ +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.ExPolicyKVStorage; +import com.jd.blockchain.storage.service.KVStorageService; +import com.jd.blockchain.storage.service.VersioningKVStorage; +import com.jd.blockchain.storage.service.utils.MemoryKVStorage; +import com.jd.blockchain.utils.Bytes; +import org.junit.Test; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +import java.lang.reflect.Method; +import java.util.Set; + +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.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 boolean isRollBack = false; + + 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.mock(MemoryKVStorage.class); + + + Answer answers = new Answer() { + + @Override + public Object answer(InvocationOnMock invocationOnMock) throws Throwable { + + Method method = invocationOnMock.getMethod(); + if (method.getName().equalsIgnoreCase("set")) { + Object arg2Obj = invocationOnMock.getArguments()[2]; + if (isRollBack) { + if (arg2Obj instanceof ExPolicyKVStorage.ExPolicy) { + return false; + } else { + return -1; + } + } else { + if (arg2Obj instanceof ExPolicyKVStorage.ExPolicy) { + return STORAGE.set((Bytes) (invocationOnMock.getArguments()[0]), (byte[])(invocationOnMock.getArguments()[1]), (ExPolicyKVStorage.ExPolicy)(arg2Obj)); + } else { + return STORAGE.set((Bytes) (invocationOnMock.getArguments()[0]), (byte[])(invocationOnMock.getArguments()[1]), (long)(arg2Obj)); + } + } + } else if ((method.getName().equalsIgnoreCase("get")) && (method.getParameterCount() == 1)) { + return STORAGE.get((Bytes)(invocationOnMock.getArguments()[0])); + } else if ((method.getName().equalsIgnoreCase("get")) && (method.getParameterCount() == 2)) { + return STORAGE.get((Bytes)(invocationOnMock.getArguments()[0]), (long)(invocationOnMock.getArguments()[1])); + } else if (method.getName().equalsIgnoreCase("getVersion")) { + return STORAGE.getVersion((Bytes)(invocationOnMock.getArguments()[0])); + } else if (method.getName().equalsIgnoreCase("getEntry")) { + return STORAGE.get((Bytes)(invocationOnMock.getArguments()[0]), (long)(invocationOnMock.getArguments()[1])); + } else if (method.getName().equalsIgnoreCase("exist")) { + return STORAGE.get((Bytes)(invocationOnMock.getArguments()[0])); + } else if (method.getName().equalsIgnoreCase("keySet")) { + return STORAGE.keySet(); + } else if (method.getName().equalsIgnoreCase("getStorageKeySet")) { + return STORAGE.getStorageKeySet(); + } else if (method.getName().equalsIgnoreCase("getValue")) { + return STORAGE.getValue((Bytes)(invocationOnMock.getArguments()[0])); + } else if (method.getName().equalsIgnoreCase("getStorageCount")) { + return STORAGE.getStorageCount(); + } else if (method.getName().equalsIgnoreCase("getExPolicyKVStorage")) { + return STORAGE.getExPolicyKVStorage(); + } else if (method.getName().equalsIgnoreCase("getVersioningKVStorage")) { + return STORAGE.getVersioningKVStorage(); + } + + return null; + } + }; + + when(STORAGE_Mock.set(any(), any(), anyLong())).thenAnswer(answers); + when(STORAGE_Mock.set(any(), any(), any(ExPolicyKVStorage.ExPolicy.class))).thenAnswer(answers); + when(STORAGE_Mock.get(any())).thenAnswer(answers); + when(STORAGE_Mock.get(any(), anyLong())).thenAnswer(answers); + when(STORAGE_Mock.getVersion(any())).thenAnswer(answers); + when(STORAGE_Mock.getEntry(any(), anyLong())).thenAnswer(answers); + when(STORAGE_Mock.exist(any())).thenAnswer(answers); + when(STORAGE_Mock.keySet()).thenAnswer(answers); + when(STORAGE_Mock.getStorageKeySet()).thenAnswer(answers); + when(STORAGE_Mock.getValue(any())).thenAnswer(answers); + when(STORAGE_Mock.getStorageCount()).thenAnswer(answers); + when(STORAGE_Mock.getExPolicyKVStorage()).thenAnswer(answers); + when(STORAGE_Mock.getVersioningKVStorage()).thenAnswer(answers); + + + // 初始化账本到指定的存储库; + ledgerHash = initLedger(STORAGE_Mock, parti0, parti1, parti2, parti3); + + System.out.println("---------- Ledger init OK !!! ----------"); + + // 加载账本; + LedgerManager ledgerManager = new LedgerManager(); + + KVStorageService kvStorageService = new KVStorageService() { + @Override + public ExPolicyKVStorage getExPolicyKVStorage() { + return STORAGE_Mock; + } + + @Override + public VersioningKVStorage getVersioningKVStorage() { + return STORAGE_Mock; + } + }; + + LedgerRepository ledgerRepo = ledgerManager.register(ledgerHash, kvStorageService); + + // 构造存储错误,并产生区块回滚 + isRollBack = true; + 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); + + //区块正常提交 + isRollBack = false; + // 生成新区块; + 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/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/MemoryKVStorage.java b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/MemoryKVStorage.java index 1cb202fa..0c2192a3 100644 --- a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/MemoryKVStorage.java +++ b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/MemoryKVStorage.java @@ -12,8 +12,6 @@ import com.jd.blockchain.utils.io.BytesMap; public class MemoryKVStorage implements ExPolicyKVStorage, VersioningKVStorage, KVStorageService, BytesMap { - public static boolean isBlockFullRollbackTest = false; - private ExistancePolicyKVStorageMap exStorage = new ExistancePolicyKVStorageMap(); private VersioningKVStorageMap verStorage = new VersioningKVStorageMap(); @@ -34,9 +32,6 @@ public class MemoryKVStorage implements ExPolicyKVStorage, VersioningKVStorage, @Override public long set(Bytes key, byte[] value, long version) { - if (isBlockFullRollbackTest) { - return -1; - } return verStorage.set(key, value, version); } diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBlockFullRollback.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBlockFullRollback.java deleted file mode 100644 index b3a68c77..00000000 --- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBlockFullRollback.java +++ /dev/null @@ -1,105 +0,0 @@ -package test.com.jd.blockchain.intgr; - -import com.jd.blockchain.crypto.*; -import com.jd.blockchain.gateway.GatewayConfigProperties; -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.DbConnectionFactory; -import com.jd.blockchain.storage.service.utils.MemoryKVStorage; -import com.jd.blockchain.tools.initializer.LedgerBindingConfig; -import com.jd.blockchain.utils.concurrent.ThreadInvoker; -import org.junit.Test; -import test.com.jd.blockchain.intgr.initializer.LedgerInitializeTest; -import test.com.jd.blockchain.intgr.initializer.LedgerInitializeWeb4Nodes; - -import static test.com.jd.blockchain.intgr.IntegrationBase.*; - -public class IntegrationBlockFullRollback { - - private static final String DB_TYPE_MEM = "mem"; - - @Test - public void test4Memory() { - test(LedgerInitConsensusConfig.bftsmartProvider, DB_TYPE_MEM, LedgerInitConsensusConfig.memConnectionStrings); - } - - public void test(String[] providers, String dbType, String[] dbConnections) { - - // 内存账本初始化 - HashDigest ledgerHash = initLedger(dbConnections); - - // 启动Peer节点 - PeerTestRunner[] peerNodes = peerNodeStart(ledgerHash, dbType); - - DbConnectionFactory dbConnectionFactory0 = peerNodes[0].getDBConnectionFactory(); - DbConnectionFactory dbConnectionFactory1 = peerNodes[1].getDBConnectionFactory(); - DbConnectionFactory dbConnectionFactory2 = peerNodes[2].getDBConnectionFactory(); - DbConnectionFactory dbConnectionFactory3 = peerNodes[3].getDBConnectionFactory(); - - String encodedBase58Pwd = KeyGenUtils.encodePasswordAsBase58(LedgerInitializeTest.PASSWORD); - - GatewayConfigProperties.KeyPairConfig gwkey0 = new GatewayConfigProperties.KeyPairConfig(); - gwkey0.setPubKeyValue(IntegrationBase.PUB_KEYS[0]); - gwkey0.setPrivKeyValue(IntegrationBase.PRIV_KEYS[0]); - gwkey0.setPrivKeyPassword(encodedBase58Pwd); - GatewayTestRunner gateway = new GatewayTestRunner("127.0.0.1", 11000, gwkey0, - peerNodes[0].getServiceAddress(), providers,null); - - ThreadInvoker.AsyncCallback gwStarting = gateway.start(); - - gwStarting.waitReturn(); - - // 执行测试用例之前,校验每个节点的一致性; - LedgerQuery[] ledgers = buildLedgers(new LedgerBindingConfig[]{ - peerNodes[0].getLedgerBindingConfig(), - peerNodes[1].getLedgerBindingConfig(), - peerNodes[2].getLedgerBindingConfig(), - peerNodes[3].getLedgerBindingConfig(), - }, - new DbConnectionFactory[]{ - dbConnectionFactory0, - dbConnectionFactory1, - dbConnectionFactory2, - dbConnectionFactory3}); - - IntegrationBase.testConsistencyAmongNodes(ledgers); - - LedgerQuery ledgerRepository = ledgers[0]; - - GatewayServiceFactory gwsrvFact = GatewayServiceFactory.connect(gateway.getServiceAddress()); - - PrivKey privkey0 = KeyGenUtils.decodePrivKeyWithRawPassword(IntegrationBase.PRIV_KEYS[0], IntegrationBase.PASSWORD); - - PubKey pubKey0 = KeyGenUtils.decodePubKey(IntegrationBase.PUB_KEYS[0]); - - AsymmetricKeypair adminKey = new AsymmetricKeypair(pubKey0, privkey0); - - BlockchainService blockchainService = gwsrvFact.getBlockchainService(); - - //Block commit will be fail, due to storage error - MemoryKVStorage.isBlockFullRollbackTest = true; - - IntegrationBase.KeyPairResponse userResponse = IntegrationBase.testSDK_BlockFullRollBack(adminKey, ledgerHash, blockchainService); - - //Block commit will be normal - MemoryKVStorage.isBlockFullRollbackTest = false; - - IntegrationBase.KeyPairResponse userResponse1 = IntegrationBase.testSDK_RegisterUser(adminKey, ledgerHash, blockchainService); - - try { - System.out.println("----------------- Init Completed -----------------"); - Thread.sleep(Integer.MAX_VALUE); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - IntegrationBase.testConsistencyAmongNodes(ledgers); - } - private HashDigest initLedger(String[] dbConnections) { - LedgerInitializeWeb4Nodes ledgerInit = new LedgerInitializeWeb4Nodes(); - HashDigest ledgerHash = ledgerInit.testInitWith4Nodes(LedgerInitConsensusConfig.bftsmartConfig, dbConnections); - System.out.printf("LedgerHash = %s \r\n", ledgerHash.toBase58()); - return ledgerHash; - } -} From 53bb8e6f08ee1e87b6098bb4c8d65a02a47bc3fa Mon Sep 17 00:00:00 2001 From: zhangshuang Date: Thu, 28 Nov 2019 14:51:10 +0800 Subject: [PATCH 4/8] solve block rollback exception --- .../bftsmart/service/BftsmartNodeServer.java | 105 ++++++------------ .../consensus/ConsensusMessageDispatcher.java | 5 + 2 files changed, 39 insertions(+), 71 deletions(-) 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 bbecdb5c..fcebcfa0 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,40 +354,6 @@ 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 */ @@ -395,56 +361,53 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer String batchId = messageHandle.beginBatch(realmName); List> asyncFutureLinkedList = new ArrayList<>(commands.length); List responseLinkedList = new ArrayList<>(); + StateSnapshot stateSnapshot = null; BatchAppResultImpl result; - try { - int msgId = 0; - - boolean isOK = true; - TransactionState transactionState = TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK; + int msgId = 0; + boolean isOK = true; + TransactionState transactionState = TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK; - try { - for (int i = 0; i < commands.length; i++) { - byte[] txContent = commands[i]; - 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; + try { + for (int i = 0; i < commands.length; i++) { + byte[] txContent = commands[i]; + AsyncFuture asyncFuture = messageHandle.processOrdered(msgId++, txContent, realmName, batchId); + asyncFutureLinkedList.add(asyncFuture); } + stateSnapshot = messageHandle.completeBatch(realmName, batchId); + } catch (Exception e) { + LOGGER.error("Error occurred while processing ordered messages or complete batch! --" + e.getMessage(), e); + messageHandle.rollbackBatch(realmName, batchId, TransactionState.IGNORED_BY_CONSENSUS_PHASE_PRECOMPUTE_ROLLBACK.CODE); + isOK = false; + } - if (isOK) { - StateSnapshot stateSnapshot = messageHandle.completeBatch(realmName, batchId); - byte[] blockHashBytes = stateSnapshot.getSnapshot(); + if (isOK) { - for (int i = 0; i < asyncFutureLinkedList.size(); i++) { - responseLinkedList.add(asyncFutureLinkedList.get(i).get()); - } + byte[] blockHashBytes = stateSnapshot.getSnapshot(); - result = new BatchAppResultImpl(responseLinkedList, blockHashBytes, batchId); - result.setErrorCode((byte) 0); + for (int i = 0; i < asyncFutureLinkedList.size(); i++) { + responseLinkedList.add(asyncFutureLinkedList.get(i).get()); + } - return result; - } else { + result = new BatchAppResultImpl(responseLinkedList, blockHashBytes, batchId); + result.setErrorCode((byte) 0); - for (int i = 0; i < commands.length; i++) { - responseLinkedList.add(createAppResponse(commands[i],transactionState)); - } + return result; + } else { - Random random = new Random(); - byte[] rand = new byte[4]; - random.nextBytes(rand); + for (int i = 0; i < commands.length; i++) { + responseLinkedList.add(createAppResponse(commands[i],transactionState)); + } - result = new BatchAppResultImpl(responseLinkedList, rand, batchId); - result.setErrorCode((byte) 1); + Random random = new Random(); + byte[] rand = new byte[4]; + random.nextBytes(rand); - return result; - } + result = new BatchAppResultImpl(responseLinkedList, rand, batchId); + result.setErrorCode((byte) 1); - } catch (Exception e) { - LOGGER.error("Error occurred while genearte batch app result! --" + e.getMessage(), e); - throw e; + return result; } + } // Block full rollback responses, generated in pre compute phase, due to tx fail 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..ceb33490 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 @@ -236,12 +236,17 @@ public class ConsensusMessageDispatcher implements MessageHandle { currBatchId = null; txResponseMap = null; txBatchProcess = null; + batchResultHandle =null; } finally { realmLock.unlock(); } } public void rollback(int reasonCode) { + + if (batchResultHandle == null) { + return; + } realmLock.lock(); try { batchResultHandle.cancel(TransactionState.valueOf((byte)reasonCode)); From 96bac609baae56b275e754aed28fc1e6bb9b1916 Mon Sep 17 00:00:00 2001 From: zhangshuang Date: Thu, 28 Nov 2019 17:48:08 +0800 Subject: [PATCH 5/8] modify test example by mockito spy --- .../ledger/core/BlockFullRollBackTest.java | 100 ++---------------- 1 file changed, 8 insertions(+), 92 deletions(-) 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 index a974844a..6c8009f9 100644 --- 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 @@ -4,24 +4,17 @@ 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.ExPolicyKVStorage; -import com.jd.blockchain.storage.service.KVStorageService; -import com.jd.blockchain.storage.service.VersioningKVStorage; import com.jd.blockchain.storage.service.utils.MemoryKVStorage; -import com.jd.blockchain.utils.Bytes; import org.junit.Test; import org.mockito.Mockito; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; - -import java.lang.reflect.Method; -import java.util.Set; 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 { @@ -41,8 +34,6 @@ public class BlockFullRollBackTest { private HashDigest ledgerHash = null; - private boolean isRollBack = false; - private BlockchainKeypair parti0 = BlockchainKeyGenerator.getInstance().generate(); private BlockchainKeypair parti1 = BlockchainKeyGenerator.getInstance().generate(); private BlockchainKeypair parti2 = BlockchainKeyGenerator.getInstance().generate(); @@ -56,72 +47,7 @@ public class BlockFullRollBackTest { final MemoryKVStorage STORAGE = new MemoryKVStorage(); - final MemoryKVStorage STORAGE_Mock = Mockito.mock(MemoryKVStorage.class); - - - Answer answers = new Answer() { - - @Override - public Object answer(InvocationOnMock invocationOnMock) throws Throwable { - - Method method = invocationOnMock.getMethod(); - if (method.getName().equalsIgnoreCase("set")) { - Object arg2Obj = invocationOnMock.getArguments()[2]; - if (isRollBack) { - if (arg2Obj instanceof ExPolicyKVStorage.ExPolicy) { - return false; - } else { - return -1; - } - } else { - if (arg2Obj instanceof ExPolicyKVStorage.ExPolicy) { - return STORAGE.set((Bytes) (invocationOnMock.getArguments()[0]), (byte[])(invocationOnMock.getArguments()[1]), (ExPolicyKVStorage.ExPolicy)(arg2Obj)); - } else { - return STORAGE.set((Bytes) (invocationOnMock.getArguments()[0]), (byte[])(invocationOnMock.getArguments()[1]), (long)(arg2Obj)); - } - } - } else if ((method.getName().equalsIgnoreCase("get")) && (method.getParameterCount() == 1)) { - return STORAGE.get((Bytes)(invocationOnMock.getArguments()[0])); - } else if ((method.getName().equalsIgnoreCase("get")) && (method.getParameterCount() == 2)) { - return STORAGE.get((Bytes)(invocationOnMock.getArguments()[0]), (long)(invocationOnMock.getArguments()[1])); - } else if (method.getName().equalsIgnoreCase("getVersion")) { - return STORAGE.getVersion((Bytes)(invocationOnMock.getArguments()[0])); - } else if (method.getName().equalsIgnoreCase("getEntry")) { - return STORAGE.get((Bytes)(invocationOnMock.getArguments()[0]), (long)(invocationOnMock.getArguments()[1])); - } else if (method.getName().equalsIgnoreCase("exist")) { - return STORAGE.get((Bytes)(invocationOnMock.getArguments()[0])); - } else if (method.getName().equalsIgnoreCase("keySet")) { - return STORAGE.keySet(); - } else if (method.getName().equalsIgnoreCase("getStorageKeySet")) { - return STORAGE.getStorageKeySet(); - } else if (method.getName().equalsIgnoreCase("getValue")) { - return STORAGE.getValue((Bytes)(invocationOnMock.getArguments()[0])); - } else if (method.getName().equalsIgnoreCase("getStorageCount")) { - return STORAGE.getStorageCount(); - } else if (method.getName().equalsIgnoreCase("getExPolicyKVStorage")) { - return STORAGE.getExPolicyKVStorage(); - } else if (method.getName().equalsIgnoreCase("getVersioningKVStorage")) { - return STORAGE.getVersioningKVStorage(); - } - - return null; - } - }; - - when(STORAGE_Mock.set(any(), any(), anyLong())).thenAnswer(answers); - when(STORAGE_Mock.set(any(), any(), any(ExPolicyKVStorage.ExPolicy.class))).thenAnswer(answers); - when(STORAGE_Mock.get(any())).thenAnswer(answers); - when(STORAGE_Mock.get(any(), anyLong())).thenAnswer(answers); - when(STORAGE_Mock.getVersion(any())).thenAnswer(answers); - when(STORAGE_Mock.getEntry(any(), anyLong())).thenAnswer(answers); - when(STORAGE_Mock.exist(any())).thenAnswer(answers); - when(STORAGE_Mock.keySet()).thenAnswer(answers); - when(STORAGE_Mock.getStorageKeySet()).thenAnswer(answers); - when(STORAGE_Mock.getValue(any())).thenAnswer(answers); - when(STORAGE_Mock.getStorageCount()).thenAnswer(answers); - when(STORAGE_Mock.getExPolicyKVStorage()).thenAnswer(answers); - when(STORAGE_Mock.getVersioningKVStorage()).thenAnswer(answers); - + final MemoryKVStorage STORAGE_Mock = Mockito.spy(STORAGE); // 初始化账本到指定的存储库; ledgerHash = initLedger(STORAGE_Mock, parti0, parti1, parti2, parti3); @@ -131,22 +57,11 @@ public class BlockFullRollBackTest { // 加载账本; LedgerManager ledgerManager = new LedgerManager(); - KVStorageService kvStorageService = new KVStorageService() { - @Override - public ExPolicyKVStorage getExPolicyKVStorage() { - return STORAGE_Mock; - } - - @Override - public VersioningKVStorage getVersioningKVStorage() { - return STORAGE_Mock; - } - }; - - LedgerRepository ledgerRepo = ledgerManager.register(ledgerHash, kvStorageService); + LedgerRepository ledgerRepo = ledgerManager.register(ledgerHash, STORAGE_Mock); // 构造存储错误,并产生区块回滚 - isRollBack = true; + doThrow(BlockRollbackException.class).when(STORAGE_Mock).set(any(), any(), anyLong()); + LedgerEditor newBlockEditor = ledgerRepo.createNextBlock(); OperationHandleRegisteration opReg = new DefaultOperationHandleRegisteration(); @@ -179,8 +94,9 @@ public class BlockFullRollBackTest { assertFalse(existUser); + doCallRealMethod().when(STORAGE_Mock).set(any(), any(), anyLong()); + //区块正常提交 - isRollBack = false; // 生成新区块; LedgerEditor newBlockEditor1 = ledgerRepo.createNextBlock(); From 7469f5802d07638e77d9e562d59c2d4103efae07 Mon Sep 17 00:00:00 2001 From: zhangshuang Date: Mon, 9 Dec 2019 16:40:16 +0800 Subject: [PATCH 6/8] modify block rollback --- .../bftsmart/service/BftsmartNodeServer.java | 81 +++--- .../consensus/service/MessageHandle.java | 8 + .../ledger/core/LedgerRepositoryImpl.java | 4 + .../core/TransactionBatchProcessor.java | 8 + .../ledger/core/TransactionEngineImpl.java | 10 + .../consensus/ConsensusMessageDispatcher.java | 29 ++- .../SDK_GateWay_Invalid_Signer_Test_.java | 97 ++++++++ .../IntegrationTestStorageErrorRollBack.java | 233 ++++++++++++++++++ 8 files changed, 416 insertions(+), 54 deletions(-) create mode 100644 source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Invalid_Signer_Test_.java create mode 100644 source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestStorageErrorRollBack.java 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 fcebcfa0..e3ef31ab 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 @@ -358,60 +358,60 @@ 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<>(); - StateSnapshot stateSnapshot = null; - BatchAppResultImpl result; + StateSnapshot newStateSnapshot = null; + StateSnapshot preStateSnapshot = null; + BatchAppResultImpl result = null; + String batchId = null; int msgId = 0; - boolean isOK = true; - TransactionState transactionState = TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK; try { + + batchId = messageHandle.beginBatch(realmName); + + preStateSnapshot = messageHandle.getStateSnapshot(realmName); + + if (preStateSnapshot == null) { + System.out.println("prev state snapshot is null"); + } + +// System.out.println("last hash = "+preStateSnapshot.getSnapshot()); + System.out.println("last height = "+preStateSnapshot.getId()); + for (int i = 0; i < commands.length; i++) { byte[] txContent = commands[i]; AsyncFuture asyncFuture = messageHandle.processOrdered(msgId++, txContent, realmName, batchId); asyncFutureLinkedList.add(asyncFuture); } - stateSnapshot = messageHandle.completeBatch(realmName, batchId); - } catch (Exception e) { - LOGGER.error("Error occurred while processing ordered messages or complete batch! --" + e.getMessage(), e); - messageHandle.rollbackBatch(realmName, batchId, TransactionState.IGNORED_BY_CONSENSUS_PHASE_PRECOMPUTE_ROLLBACK.CODE); - isOK = false; - } - - if (isOK) { - - byte[] blockHashBytes = stateSnapshot.getSnapshot(); + newStateSnapshot = messageHandle.completeBatch(realmName, batchId); +// System.out.println("new hash = "+newStateSnapshot.getSnapshot()); + System.out.println("new height = "+newStateSnapshot.getId()); for (int i = 0; i < asyncFutureLinkedList.size(); i++) { responseLinkedList.add(asyncFutureLinkedList.get(i).get()); } - result = new BatchAppResultImpl(responseLinkedList, blockHashBytes, batchId); + result = new BatchAppResultImpl(responseLinkedList, newStateSnapshot.getSnapshot(), batchId); result.setErrorCode((byte) 0); - return result; - } else { - + } catch (Exception e) { + LOGGER.error("Error occurred while pre compute app! --" + e.getMessage(), e); +// messageHandle.rollbackBatch(realmName, batchId, TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK.CODE); for (int i = 0; i < commands.length; i++) { - responseLinkedList.add(createAppResponse(commands[i],transactionState)); + responseLinkedList.add(createAppResponse(commands[i],TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK)); } - Random random = new Random(); - byte[] rand = new byte[4]; - random.nextBytes(rand); - - result = new BatchAppResultImpl(responseLinkedList, rand, batchId); + result = new BatchAppResultImpl(responseLinkedList,preStateSnapshot.getSnapshot(), batchId); result.setErrorCode((byte) 1); - - return result; } + return result; } - // Block full rollback responses, generated in pre compute phase, due to tx fail - 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()); @@ -421,25 +421,8 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer return BinaryProtocol.encode(resp, TransactionResponse.class); } - - - //Pre compute block hash values are inconsistent, update batch messages to new state - public List preCompInconsistentAppResps(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); - updatedResponses.add(BinaryProtocol.encode(resp, TransactionResponse.class)); - } - - return updatedResponses; - } - - - //Consensus accept phase will terminate, pre compute commit exception occurs, update batch messages execute state to block full rollback - public List blockRollbackAppResps(List asyncResponseLinkedList) { + //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++) { @@ -472,7 +455,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/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/TransactionBatchProcessor.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionBatchProcessor.java index e347f101..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(); } 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/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 ceb33490..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); @@ -243,16 +261,17 @@ public class ConsensusMessageDispatcher implements MessageHandle { } public void rollback(int reasonCode) { - - if (batchResultHandle == null) { - return; - } 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/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Invalid_Signer_Test_.java b/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Invalid_Signer_Test_.java new file mode 100644 index 00000000..00790ebe --- /dev/null +++ b/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Invalid_Signer_Test_.java @@ -0,0 +1,97 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: test.com.jd.blockchain.sdk.test.SDK_GateWay_InsertData_Test + * Author: shaozhuguang + * Department: 区块链研发部 + * Date: 2018/9/4 上午11:06 + * Description: 插入数据测试 + */ +package test.com.jd.blockchain.sdk.test; + +import com.jd.blockchain.binaryproto.DataContractRegistry; +import com.jd.blockchain.crypto.*; +import com.jd.blockchain.ledger.*; +import com.jd.blockchain.sdk.BlockchainService; +import com.jd.blockchain.sdk.client.GatewayServiceFactory; +import com.jd.blockchain.transaction.TxResponseMessage; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +/** + * 注册具有无效签名的用户账户 + * @author zhangshuang + * @create 2019/12/6 + * @since 1.0.0 + */ + +public class SDK_GateWay_Invalid_Signer_Test_ { + + private PrivKey privKey; + private PubKey pubKey; + + private BlockchainKeypair CLIENT_CERT = null; + + private String GATEWAY_IPADDR = null; + + private int GATEWAY_PORT; + + private boolean SECURE; + + private BlockchainService service; + + public static final String PASSWORD = "abc"; + + public static final String PUB_KEYS = "3snPdw7i7Pb3B5AxpSXy6YVruvftugNQ7rB7k2KWukhBwKQhFBFagT"; + public static final String PRIV_KEYS = "177gjtSgSdUF3LwRFGhzbpZZxmXXChsnwbuuLCG1V9KYfVuuxLwXGmZCp5FGUvsenhwBQLV"; + + @Before + public void init() { + + privKey = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS, PASSWORD); + pubKey = KeyGenUtils.decodePubKey(PUB_KEYS); + + CLIENT_CERT = new BlockchainKeypair(SDK_GateWay_KeyPair_Para.pubKey0, SDK_GateWay_KeyPair_Para.privkey0); + GATEWAY_IPADDR = "localhost"; + GATEWAY_PORT = 11000; + SECURE = false; + GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IPADDR, GATEWAY_PORT, SECURE, + CLIENT_CERT); + service = serviceFactory.getBlockchainService(); + + DataContractRegistry.register(TransactionContent.class); + DataContractRegistry.register(TransactionContentBody.class); + DataContractRegistry.register(TransactionRequest.class); + DataContractRegistry.register(NodeRequest.class); + DataContractRegistry.register(EndpointRequest.class); + DataContractRegistry.register(TransactionResponse.class); + } + + @Test + public void registerUser_Test() { + HashDigest[] ledgerHashs = service.getLedgerHashs(); + // 在本地定义注册账号的 TX; + TransactionTemplate txTemp = service.newTransaction(ledgerHashs[0]); + + //existed signer + AsymmetricKeypair keyPair = new BlockchainKeypair(pubKey, privKey); + + BlockchainKeypair user = BlockchainKeyGenerator.getInstance().generate(); + + // 注册 + txTemp.users().register(user.getIdentity()); + + // TX 准备就绪; + PreparedTransaction prepTx = txTemp.prepare(); + + // 使用私钥进行签名; + prepTx.sign(keyPair); + + // 提交交易; + TransactionResponse transactionResponse = prepTx.commit(); + + assertTrue(transactionResponse.getExecutionState().CODE == TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK.CODE); + + } +} \ No newline at end of file diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestStorageErrorRollBack.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestStorageErrorRollBack.java new file mode 100644 index 00000000..0f8a9b52 --- /dev/null +++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestStorageErrorRollBack.java @@ -0,0 +1,233 @@ +//package test.com.jd.blockchain.intgr; +// +//import com.jd.blockchain.consensus.ConsensusProviders; +//import com.jd.blockchain.consensus.bftsmart.BftsmartConsensusSettings; +//import com.jd.blockchain.crypto.*; +//import com.jd.blockchain.gateway.GatewayConfigProperties; +//import com.jd.blockchain.ledger.BlockRollbackException; +//import com.jd.blockchain.ledger.BlockchainKeypair; +//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.DbConnection; +//import com.jd.blockchain.storage.service.DbConnectionFactory; +//import com.jd.blockchain.storage.service.ExPolicyKVStorage; +//import com.jd.blockchain.storage.service.KVStorageService; +//import com.jd.blockchain.storage.service.utils.MemoryKVStorage; +//import com.jd.blockchain.tools.initializer.LedgerBindingConfig; +//import com.jd.blockchain.utils.Bytes; +//import com.jd.blockchain.utils.concurrent.ThreadInvoker; +//import org.junit.Test; +//import org.mockito.Mockito; +//import org.mockito.invocation.InvocationOnMock; +//import org.mockito.stubbing.Answer; +//import test.com.jd.blockchain.intgr.initializer.LedgerInitializeTest; +//import test.com.jd.blockchain.intgr.initializer.LedgerInitializeWeb4Nodes; +// +//import java.lang.reflect.Method; +//import java.util.concurrent.CountDownLatch; +//import java.util.concurrent.ExecutorService; +//import java.util.concurrent.Executors; +// +//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 test.com.jd.blockchain.intgr.IntegrationBase.*; +// +//public class IntegrationTestStorageErrorRollBack { +// +// private static final boolean isRegisterUser = true; +// +// private static final boolean isRegisterDataAccount = false; +// +// private static final boolean isWriteKv = false; +// +// private static final String DB_TYPE_MEM = "mem"; +// +// public static final String BFTSMART_PROVIDER = "com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider"; +// +// public boolean isRollBack = false; +// +// @Test +// public void test4Memory() { +// test(LedgerInitConsensusConfig.bftsmartProvider, DB_TYPE_MEM, LedgerInitConsensusConfig.memConnectionStrings); +// } +// +// public void test(String[] providers, String dbType, String[] dbConnections) { +// +// +// final ExecutorService sendReqExecutors = Executors.newFixedThreadPool(20); +// +// // 内存账本初始化 +// HashDigest ledgerHash = initLedger(dbConnections); +// +// System.out.println("---------------init OK-------------------"); +// +// // 启动Peer节点 +// PeerTestRunner[] peerNodes = peerNodeStart(ledgerHash, dbType); +// +// System.out.println("---------------peer start OK-------------------"); +// String encodedBase58Pwd = KeyGenUtils.encodePasswordAsBase58(LedgerInitializeTest.PASSWORD); +// +// GatewayConfigProperties.KeyPairConfig gwkey0 = new GatewayConfigProperties.KeyPairConfig(); +// gwkey0.setPubKeyValue(IntegrationBase.PUB_KEYS[0]); +// gwkey0.setPrivKeyValue(IntegrationBase.PRIV_KEYS[0]); +// gwkey0.setPrivKeyPassword(encodedBase58Pwd); +// GatewayTestRunner gateway = new GatewayTestRunner("127.0.0.1", 11000, gwkey0, +// peerNodes[0].getServiceAddress(), providers,null); +// +// ThreadInvoker.AsyncCallback gwStarting = gateway.start(); +// +// gwStarting.waitReturn(); +// +// LedgerQuery[] ledgers = new LedgerQuery[peerNodes.length]; +// LedgerManager[] ledgerManagers = new LedgerManager[peerNodes.length]; +// LedgerBindingConfig[] ledgerBindingConfigs = new LedgerBindingConfig[peerNodes.length]; +// DbConnection[] connections = new DbConnection[peerNodes.length]; +// MemoryKVStorage[] storageMocks = new MemoryKVStorage[peerNodes.length]; +// for (int i = 0; i < peerNodes.length; i++) { +// ledgerManagers[i] = new LedgerManager(); +// ledgerBindingConfigs[i] = peerNodes[i].getLedgerBindingConfig(); +// connections[i] = peerNodes[i].getDBConnectionFactory().connect(ledgerBindingConfigs[i].getLedger(ledgerHash).getDbConnection().getUri()); +// System.out.printf("StorageService[%s] -> %s \r\n", i, connections[i].getStorageService()); +// storageMocks[i] = Mockito.spy((MemoryKVStorage)(connections[i].getStorageService())); +// ledgers[i] = ledgerManagers[i].register(ledgerHash, storageMocks[i]); +// } +// +// final MemoryKVStorage STORAGE_Mock = Mockito.mock(MemoryKVStorage.class); +// +// Answer answers = new Answer() { +// +// @Override +// public Object answer(InvocationOnMock invocationOnMock) throws Throwable { +// +// Method method = invocationOnMock.getMethod(); +// if (method.getName().equalsIgnoreCase("set")) { +// Object arg2Obj = invocationOnMock.getArguments()[2]; +// if (isRollBack) { +// if (arg2Obj instanceof ExPolicyKVStorage.ExPolicy) { +// return false; +// } else { +// return -1; +// } +// } else { +// if (arg2Obj instanceof ExPolicyKVStorage.ExPolicy) { +// return STORAG.set((Bytes) (invocationOnMock.getArguments()[0]), (byte[]) (invocationOnMock.getArguments()[1]), (ExPolicyKVStorage.ExPolicy) (arg2Obj)); +// } else { +// return STORAGE.set((Bytes) (invocationOnMock.getArguments()[0]), (byte[]) (invocationOnMock.getArguments()[1]), (long) (arg2Obj)); +// } +// } +// } else if ((method.getName().equalsIgnoreCase("get")) && (method.getParameterCount() == 1)) { +// return STORAGE.get((Bytes) (invocationOnMock.getArguments()[0])); +// } else if ((method.getName().equalsIgnoreCase("get")) && (method.getParameterCount() == 2)) { +// return STORAGE.get((Bytes) (invocationOnMock.getArguments()[0]), (long) (invocationOnMock.getArguments()[1])); +// } else if (method.getName().equalsIgnoreCase("getVersion")) { +// return STORAGE.getVersion((Bytes) (invocationOnMock.getArguments()[0])); +// } else if (method.getName().equalsIgnoreCase("getEntry")) { +// return STORAGE.get((Bytes) (invocationOnMock.getArguments()[0]), (long) (invocationOnMock.getArguments()[1])); +// } else if (method.getName().equalsIgnoreCase("exist")) { +// return STORAGE.get((Bytes) (invocationOnMock.getArguments()[0])); +// } else if (method.getName().equalsIgnoreCase("keySet")) { +// return STORAGE.keySet(); +// } else if (method.getName().equalsIgnoreCase("getStorageKeySet")) { +// return STORAGE.getStorageKeySet(); +// } else if (method.getName().equalsIgnoreCase("getValue")) { +// return STORAGE.getValue((Bytes) (invocationOnMock.getArguments()[0])); +// } else if (method.getName().equalsIgnoreCase("getStorageCount")) { +// return STORAGE.getStorageCount(); +// } else if (method.getName().equalsIgnoreCase("getExPolicyKVStorage")) { +// return STORAGE.getExPolicyKVStorage(); +// } else if (method.getName().equalsIgnoreCase("getVersioningKVStorage")) { +// return STORAGE.getVersioningKVStorage(); +// } +// +// return null; +// } +// }; +// +// when(STORAGE_Mock.set(any(), any(), anyLong())).thenAnswer(answers); +// when(STORAGE_Mock.set(any(), any(), any(ExPolicyKVStorage.ExPolicy.class))).thenAnswer(answers); +// when(STORAGE_Mock.get(any())).thenAnswer(answers); +// when(STORAGE_Mock.get(any(), anyLong())).thenAnswer(answers); +// when(STORAGE_Mock.getVersion(any())).thenAnswer(answers); +// when(STORAGE_Mock.getEntry(any(), anyLong())).thenAnswer(answers); +// when(STORAGE_Mock.exist(any())).thenAnswer(answers); +// when(STORAGE_Mock.keySet()).thenAnswer(answers); +// when(STORAGE_Mock.getStorageKeySet()).thenAnswer(answers); +// when(STORAGE_Mock.getValue(any())).thenAnswer(answers); +// when(STORAGE_Mock.getStorageCount()).thenAnswer(answers); +// when(STORAGE_Mock.getExPolicyKVStorage()).thenAnswer(answers); +// when(STORAGE_Mock.getVersioningKVStorage()).thenAnswer(answers); +// +// +// IntegrationBase.testConsistencyAmongNodes(ledgers); +// +// LedgerQuery ledgerRepository = ledgers[0]; +// +// GatewayServiceFactory gwsrvFact = GatewayServiceFactory.connect(gateway.getServiceAddress()); +// +// PrivKey privkey0 = KeyGenUtils.decodePrivKeyWithRawPassword(IntegrationBase.PRIV_KEYS[0], IntegrationBase.PASSWORD); +// +// PubKey pubKey0 = KeyGenUtils.decodePubKey(IntegrationBase.PUB_KEYS[0]); +// +// AsymmetricKeypair adminKey = new AsymmetricKeypair(pubKey0, privkey0); +// +// BlockchainService blockchainService = gwsrvFact.getBlockchainService(); +// +// int size = 15; +// CountDownLatch countDownLatch = new CountDownLatch(size); +// if (isRegisterUser) { +// for (int i = 0; i < size; i++) { +// sendReqExecutors.execute(() -> { +// +// System.out.printf(" sdk execute time = %s threadId = %s \r\n", System.currentTimeMillis(), Thread.currentThread().getId()); +// KeyPairResponse userResponse = IntegrationBase.testSDK_RegisterUser(adminKey, ledgerHash, blockchainService); +// +//// validKeyPair(userResponse, ledgerRepository, IntegrationBase.KeyPairType.USER); +// countDownLatch.countDown(); +// }); +// } +// } +// try { +// countDownLatch.await(); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// } +// +// for (int i = 0; i < peerNodes.length; i++) { +// doCallRealMethod().when(storageMocks[i]).set(any(), any(), anyLong()); +// } +// +// if (isRegisterDataAccount) { +// KeyPairResponse dataAccountResponse = IntegrationBase.testSDK_RegisterDataAccount(adminKey, ledgerHash, blockchainService); +// +// validKeyPair(dataAccountResponse, ledgerRepository, KeyPairType.DATAACCOUNT); +// +// if (isWriteKv) { +// +// for (int m = 0; m < 13; m++) { +// BlockchainKeypair da = dataAccountResponse.keyPair; +// KvResponse kvResponse = IntegrationBase.testSDK_InsertData(adminKey, ledgerHash, blockchainService, da.getAddress()); +// validKvWrite(kvResponse, ledgerRepository, blockchainService); +// } +// } +// } +// +// try { +// System.out.println("----------------- Init Completed -----------------"); +// Thread.sleep(Integer.MAX_VALUE); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// } +// +// IntegrationBase.testConsistencyAmongNodes(ledgers); +// } +// private HashDigest initLedger(String[] dbConnections) { +// LedgerInitializeWeb4Nodes ledgerInit = new LedgerInitializeWeb4Nodes(); +// HashDigest ledgerHash = ledgerInit.testInitWith4Nodes(LedgerInitConsensusConfig.bftsmartConfig, dbConnections); +// System.out.printf("LedgerHash = %s \r\n", ledgerHash.toBase58()); +// return ledgerHash; +// } +//} From e303674394e09c79a651e069829746a75516f5b9 Mon Sep 17 00:00:00 2001 From: zhangshuang Date: Wed, 11 Dec 2019 09:56:06 +0800 Subject: [PATCH 7/8] add integrate test --- .../jd/blockchain/peer/PeerServerBooter.java | 4 +- .../blockchain/intgr/IntegratedContext.java | 8 +- .../jd/blockchain/intgr/IntegrationTest.java | 111 +++++---- .../jd/blockchain/intgr/TestDbFactory.java | 140 +++++++++++ .../blockchain/intgr/TestMemoryKVStorage.java | 24 ++ .../intgr/perf/LedgerInitializeTest.java | 17 +- .../intgr/perf/LedgerInitializeWebTest.java | 32 ++- .../main/resources/ledger_init_test_web2.init | 5 +- .../IntegrationTestStorageErrorRollBack.java | 233 ------------------ 9 files changed, 260 insertions(+), 314 deletions(-) create mode 100644 source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/TestDbFactory.java create mode 100644 source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/TestMemoryKVStorage.java delete mode 100644 source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestStorageErrorRollBack.java 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/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..795bdb26 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,7 +6,9 @@ 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; @@ -44,7 +46,7 @@ public class IntegratedContext { private LedgerManager ledgerManager; - private CompositeConnectionFactory storageDB; + private DbConnectionFactory storageDB; private LedgerBindingConfig bindingConfig; @@ -60,7 +62,7 @@ public class IntegratedContext { return ledgerManager; } - public CompositeConnectionFactory getStorageDB() { + public DbConnectionFactory getStorageDB() { return storageDB; } @@ -84,7 +86,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..219ca288 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 @@ -8,6 +8,9 @@ import java.util.Properties; import java.util.Random; import java.util.concurrent.CountDownLatch; +import com.jd.blockchain.ledger.*; +import com.jd.blockchain.storage.service.impl.composite.CompositeConnectionFactory; +import com.jd.blockchain.utils.concurrent.ThreadInvoker; import org.springframework.core.io.ClassPathResource; import com.jd.blockchain.consensus.ConsensusProvider; @@ -21,20 +24,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; @@ -73,16 +62,10 @@ 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); - // } - - public static void main_(String[] args) { + 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); @@ -100,10 +83,10 @@ public class IntegrationTest { NetworkAddress peerSrvAddr3 = new NetworkAddress("127.0.0.1", 10230); PeerTestRunner peer3 = new PeerTestRunner(peerSrvAddr3, node3.getBindingConfig(), node3.getStorageDB()); - 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,30 +99,24 @@ 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); testSDK(gateway0, context); + System.out.println("------IntegrationTest Ok--------"); + // 执行测试用例之后,校验每个节点的一致性; - // testConsistencyAmongNodes(context); +// testConsistencyAmongNodes(context); } /** @@ -147,7 +124,7 @@ public class IntegrationTest { * * @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 +141,30 @@ public class IntegrationTest { } } + 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); + + // 连接网关; + GatewayServiceFactory gwsrvFact = GatewayServiceFactory.connect(gateway.getServiceAddress()); + BlockchainService bcsrv = gwsrvFact.getBlockchainService(); + + HashDigest[] ledgerHashs = bcsrv.getLedgerHashs(); + + AsymmetricKeypair adminKey = context.getNode(0).getPartiKeyPair(); + + BlockchainKeypair newUserAcount = testSDK_RegisterUser(adminKey, ledgerHashs[0], bcsrv, 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 testSDK(GatewayTestRunner gateway, IntegratedContext context) { // 连接网关; GatewayServiceFactory gwsrvFact = GatewayServiceFactory.connect(gateway.getServiceAddress()); @@ -427,15 +428,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 +466,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(); @@ -542,7 +553,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/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/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..e31e015d 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,7 @@ import java.io.InputStream; import java.util.Properties; import java.util.concurrent.CountDownLatch; +import com.jd.blockchain.storage.service.DbConnectionFactory; import org.springframework.boot.SpringApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.io.ClassPathResource; @@ -52,6 +53,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 +75,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 +244,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() @@ -339,9 +341,9 @@ public class LedgerInitializeWebTest { throw new IllegalStateException(e.getMessage(), e); } } - - 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 +367,7 @@ public class LedgerInitializeWebTest { private volatile LedgerManager ledgerManager; - private volatile CompositeConnectionFactory db; + private volatile DbConnectionFactory db; private int id; @@ -429,21 +431,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 @@ -460,6 +455,7 @@ public class LedgerInitializeWebTest { return invoker.start(); } + public LedgerInitProposal preparePermision(PrivKey privKey, LedgerInitConfiguration initConfig) { return controller.prepareLocalPermission(id, privKey, initConfig); } @@ -517,7 +513,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/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/IntegrationTestStorageErrorRollBack.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestStorageErrorRollBack.java deleted file mode 100644 index 0f8a9b52..00000000 --- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestStorageErrorRollBack.java +++ /dev/null @@ -1,233 +0,0 @@ -//package test.com.jd.blockchain.intgr; -// -//import com.jd.blockchain.consensus.ConsensusProviders; -//import com.jd.blockchain.consensus.bftsmart.BftsmartConsensusSettings; -//import com.jd.blockchain.crypto.*; -//import com.jd.blockchain.gateway.GatewayConfigProperties; -//import com.jd.blockchain.ledger.BlockRollbackException; -//import com.jd.blockchain.ledger.BlockchainKeypair; -//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.DbConnection; -//import com.jd.blockchain.storage.service.DbConnectionFactory; -//import com.jd.blockchain.storage.service.ExPolicyKVStorage; -//import com.jd.blockchain.storage.service.KVStorageService; -//import com.jd.blockchain.storage.service.utils.MemoryKVStorage; -//import com.jd.blockchain.tools.initializer.LedgerBindingConfig; -//import com.jd.blockchain.utils.Bytes; -//import com.jd.blockchain.utils.concurrent.ThreadInvoker; -//import org.junit.Test; -//import org.mockito.Mockito; -//import org.mockito.invocation.InvocationOnMock; -//import org.mockito.stubbing.Answer; -//import test.com.jd.blockchain.intgr.initializer.LedgerInitializeTest; -//import test.com.jd.blockchain.intgr.initializer.LedgerInitializeWeb4Nodes; -// -//import java.lang.reflect.Method; -//import java.util.concurrent.CountDownLatch; -//import java.util.concurrent.ExecutorService; -//import java.util.concurrent.Executors; -// -//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 test.com.jd.blockchain.intgr.IntegrationBase.*; -// -//public class IntegrationTestStorageErrorRollBack { -// -// private static final boolean isRegisterUser = true; -// -// private static final boolean isRegisterDataAccount = false; -// -// private static final boolean isWriteKv = false; -// -// private static final String DB_TYPE_MEM = "mem"; -// -// public static final String BFTSMART_PROVIDER = "com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider"; -// -// public boolean isRollBack = false; -// -// @Test -// public void test4Memory() { -// test(LedgerInitConsensusConfig.bftsmartProvider, DB_TYPE_MEM, LedgerInitConsensusConfig.memConnectionStrings); -// } -// -// public void test(String[] providers, String dbType, String[] dbConnections) { -// -// -// final ExecutorService sendReqExecutors = Executors.newFixedThreadPool(20); -// -// // 内存账本初始化 -// HashDigest ledgerHash = initLedger(dbConnections); -// -// System.out.println("---------------init OK-------------------"); -// -// // 启动Peer节点 -// PeerTestRunner[] peerNodes = peerNodeStart(ledgerHash, dbType); -// -// System.out.println("---------------peer start OK-------------------"); -// String encodedBase58Pwd = KeyGenUtils.encodePasswordAsBase58(LedgerInitializeTest.PASSWORD); -// -// GatewayConfigProperties.KeyPairConfig gwkey0 = new GatewayConfigProperties.KeyPairConfig(); -// gwkey0.setPubKeyValue(IntegrationBase.PUB_KEYS[0]); -// gwkey0.setPrivKeyValue(IntegrationBase.PRIV_KEYS[0]); -// gwkey0.setPrivKeyPassword(encodedBase58Pwd); -// GatewayTestRunner gateway = new GatewayTestRunner("127.0.0.1", 11000, gwkey0, -// peerNodes[0].getServiceAddress(), providers,null); -// -// ThreadInvoker.AsyncCallback gwStarting = gateway.start(); -// -// gwStarting.waitReturn(); -// -// LedgerQuery[] ledgers = new LedgerQuery[peerNodes.length]; -// LedgerManager[] ledgerManagers = new LedgerManager[peerNodes.length]; -// LedgerBindingConfig[] ledgerBindingConfigs = new LedgerBindingConfig[peerNodes.length]; -// DbConnection[] connections = new DbConnection[peerNodes.length]; -// MemoryKVStorage[] storageMocks = new MemoryKVStorage[peerNodes.length]; -// for (int i = 0; i < peerNodes.length; i++) { -// ledgerManagers[i] = new LedgerManager(); -// ledgerBindingConfigs[i] = peerNodes[i].getLedgerBindingConfig(); -// connections[i] = peerNodes[i].getDBConnectionFactory().connect(ledgerBindingConfigs[i].getLedger(ledgerHash).getDbConnection().getUri()); -// System.out.printf("StorageService[%s] -> %s \r\n", i, connections[i].getStorageService()); -// storageMocks[i] = Mockito.spy((MemoryKVStorage)(connections[i].getStorageService())); -// ledgers[i] = ledgerManagers[i].register(ledgerHash, storageMocks[i]); -// } -// -// final MemoryKVStorage STORAGE_Mock = Mockito.mock(MemoryKVStorage.class); -// -// Answer answers = new Answer() { -// -// @Override -// public Object answer(InvocationOnMock invocationOnMock) throws Throwable { -// -// Method method = invocationOnMock.getMethod(); -// if (method.getName().equalsIgnoreCase("set")) { -// Object arg2Obj = invocationOnMock.getArguments()[2]; -// if (isRollBack) { -// if (arg2Obj instanceof ExPolicyKVStorage.ExPolicy) { -// return false; -// } else { -// return -1; -// } -// } else { -// if (arg2Obj instanceof ExPolicyKVStorage.ExPolicy) { -// return STORAG.set((Bytes) (invocationOnMock.getArguments()[0]), (byte[]) (invocationOnMock.getArguments()[1]), (ExPolicyKVStorage.ExPolicy) (arg2Obj)); -// } else { -// return STORAGE.set((Bytes) (invocationOnMock.getArguments()[0]), (byte[]) (invocationOnMock.getArguments()[1]), (long) (arg2Obj)); -// } -// } -// } else if ((method.getName().equalsIgnoreCase("get")) && (method.getParameterCount() == 1)) { -// return STORAGE.get((Bytes) (invocationOnMock.getArguments()[0])); -// } else if ((method.getName().equalsIgnoreCase("get")) && (method.getParameterCount() == 2)) { -// return STORAGE.get((Bytes) (invocationOnMock.getArguments()[0]), (long) (invocationOnMock.getArguments()[1])); -// } else if (method.getName().equalsIgnoreCase("getVersion")) { -// return STORAGE.getVersion((Bytes) (invocationOnMock.getArguments()[0])); -// } else if (method.getName().equalsIgnoreCase("getEntry")) { -// return STORAGE.get((Bytes) (invocationOnMock.getArguments()[0]), (long) (invocationOnMock.getArguments()[1])); -// } else if (method.getName().equalsIgnoreCase("exist")) { -// return STORAGE.get((Bytes) (invocationOnMock.getArguments()[0])); -// } else if (method.getName().equalsIgnoreCase("keySet")) { -// return STORAGE.keySet(); -// } else if (method.getName().equalsIgnoreCase("getStorageKeySet")) { -// return STORAGE.getStorageKeySet(); -// } else if (method.getName().equalsIgnoreCase("getValue")) { -// return STORAGE.getValue((Bytes) (invocationOnMock.getArguments()[0])); -// } else if (method.getName().equalsIgnoreCase("getStorageCount")) { -// return STORAGE.getStorageCount(); -// } else if (method.getName().equalsIgnoreCase("getExPolicyKVStorage")) { -// return STORAGE.getExPolicyKVStorage(); -// } else if (method.getName().equalsIgnoreCase("getVersioningKVStorage")) { -// return STORAGE.getVersioningKVStorage(); -// } -// -// return null; -// } -// }; -// -// when(STORAGE_Mock.set(any(), any(), anyLong())).thenAnswer(answers); -// when(STORAGE_Mock.set(any(), any(), any(ExPolicyKVStorage.ExPolicy.class))).thenAnswer(answers); -// when(STORAGE_Mock.get(any())).thenAnswer(answers); -// when(STORAGE_Mock.get(any(), anyLong())).thenAnswer(answers); -// when(STORAGE_Mock.getVersion(any())).thenAnswer(answers); -// when(STORAGE_Mock.getEntry(any(), anyLong())).thenAnswer(answers); -// when(STORAGE_Mock.exist(any())).thenAnswer(answers); -// when(STORAGE_Mock.keySet()).thenAnswer(answers); -// when(STORAGE_Mock.getStorageKeySet()).thenAnswer(answers); -// when(STORAGE_Mock.getValue(any())).thenAnswer(answers); -// when(STORAGE_Mock.getStorageCount()).thenAnswer(answers); -// when(STORAGE_Mock.getExPolicyKVStorage()).thenAnswer(answers); -// when(STORAGE_Mock.getVersioningKVStorage()).thenAnswer(answers); -// -// -// IntegrationBase.testConsistencyAmongNodes(ledgers); -// -// LedgerQuery ledgerRepository = ledgers[0]; -// -// GatewayServiceFactory gwsrvFact = GatewayServiceFactory.connect(gateway.getServiceAddress()); -// -// PrivKey privkey0 = KeyGenUtils.decodePrivKeyWithRawPassword(IntegrationBase.PRIV_KEYS[0], IntegrationBase.PASSWORD); -// -// PubKey pubKey0 = KeyGenUtils.decodePubKey(IntegrationBase.PUB_KEYS[0]); -// -// AsymmetricKeypair adminKey = new AsymmetricKeypair(pubKey0, privkey0); -// -// BlockchainService blockchainService = gwsrvFact.getBlockchainService(); -// -// int size = 15; -// CountDownLatch countDownLatch = new CountDownLatch(size); -// if (isRegisterUser) { -// for (int i = 0; i < size; i++) { -// sendReqExecutors.execute(() -> { -// -// System.out.printf(" sdk execute time = %s threadId = %s \r\n", System.currentTimeMillis(), Thread.currentThread().getId()); -// KeyPairResponse userResponse = IntegrationBase.testSDK_RegisterUser(adminKey, ledgerHash, blockchainService); -// -//// validKeyPair(userResponse, ledgerRepository, IntegrationBase.KeyPairType.USER); -// countDownLatch.countDown(); -// }); -// } -// } -// try { -// countDownLatch.await(); -// } catch (InterruptedException e) { -// e.printStackTrace(); -// } -// -// for (int i = 0; i < peerNodes.length; i++) { -// doCallRealMethod().when(storageMocks[i]).set(any(), any(), anyLong()); -// } -// -// if (isRegisterDataAccount) { -// KeyPairResponse dataAccountResponse = IntegrationBase.testSDK_RegisterDataAccount(adminKey, ledgerHash, blockchainService); -// -// validKeyPair(dataAccountResponse, ledgerRepository, KeyPairType.DATAACCOUNT); -// -// if (isWriteKv) { -// -// for (int m = 0; m < 13; m++) { -// BlockchainKeypair da = dataAccountResponse.keyPair; -// KvResponse kvResponse = IntegrationBase.testSDK_InsertData(adminKey, ledgerHash, blockchainService, da.getAddress()); -// validKvWrite(kvResponse, ledgerRepository, blockchainService); -// } -// } -// } -// -// try { -// System.out.println("----------------- Init Completed -----------------"); -// Thread.sleep(Integer.MAX_VALUE); -// } catch (InterruptedException e) { -// e.printStackTrace(); -// } -// -// IntegrationBase.testConsistencyAmongNodes(ledgers); -// } -// private HashDigest initLedger(String[] dbConnections) { -// LedgerInitializeWeb4Nodes ledgerInit = new LedgerInitializeWeb4Nodes(); -// HashDigest ledgerHash = ledgerInit.testInitWith4Nodes(LedgerInitConsensusConfig.bftsmartConfig, dbConnections); -// System.out.printf("LedgerHash = %s \r\n", ledgerHash.toBase58()); -// return ledgerHash; -// } -//} From 0255ff9a4576aba1c71a7d912fef42b961e273f7 Mon Sep 17 00:00:00 2001 From: zhangshuang Date: Fri, 13 Dec 2019 10:48:14 +0800 Subject: [PATCH 8/8] solve block rollback --- .../bftsmart/service/BftsmartNodeServer.java | 8 +- .../consensus/ConsensusProviders.java | 3 +- .../core/TransactionBatchProcessorTest.java | 2 +- .../peer/ledger/LedgerConfigurer.java | 2 + source/pom.xml | 2 +- .../SDK_GateWay_Invalid_Signer_Test_.java | 97 ------ .../test/SDK_GateWay_Tx_RollBack_Test_.java | 114 -------- source/test/test-integration/pom.xml | 5 + .../blockchain/intgr/IntegratedContext.java | 10 + .../jd/blockchain/intgr/IntegrationTest.java | 275 +++++++++++++++++- .../jd/blockchain/intgr/PeerTestRunner.java | 7 +- .../intgr/consensus/ConsensusTest.java | 8 +- .../intgr/perf/GlobalPerformanceTest.java | 8 +- .../intgr/perf/LedgerInitializeWebTest.java | 23 +- .../src/main/resources/bftsmart.config | 27 +- .../blockchain/intgr/IntegrationBaseTest.java | 8 +- .../jd/blockchain/intgr/IntegrationTest2.java | 8 +- .../intgr/IntegrationTestDataAccount.java | 8 +- 18 files changed, 324 insertions(+), 291 deletions(-) delete mode 100644 source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Invalid_Signer_Test_.java delete mode 100644 source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Tx_RollBack_Test_.java 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 e3ef31ab..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 @@ -374,20 +374,15 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer preStateSnapshot = messageHandle.getStateSnapshot(realmName); if (preStateSnapshot == null) { - System.out.println("prev state snapshot is null"); + throw new IllegalStateException("Pre block state snapshot is null!"); } -// System.out.println("last hash = "+preStateSnapshot.getSnapshot()); - System.out.println("last height = "+preStateSnapshot.getId()); - for (int i = 0; i < commands.length; i++) { byte[] txContent = commands[i]; AsyncFuture asyncFuture = messageHandle.processOrdered(msgId++, txContent, realmName, batchId); asyncFutureLinkedList.add(asyncFuture); } newStateSnapshot = messageHandle.completeBatch(realmName, batchId); -// System.out.println("new hash = "+newStateSnapshot.getSnapshot()); - System.out.println("new height = "+newStateSnapshot.getId()); for (int i = 0; i < asyncFutureLinkedList.size(); i++) { responseLinkedList.add(asyncFutureLinkedList.get(i).get()); @@ -398,7 +393,6 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer } catch (Exception e) { LOGGER.error("Error occurred while pre compute app! --" + e.getMessage(), e); -// messageHandle.rollbackBatch(realmName, batchId, TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK.CODE); for (int i = 0; i < commands.length; i++) { responseLinkedList.add(createAppResponse(commands[i],TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK)); } 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/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/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 5b9d0c10..eb777e4d 100644 --- a/source/pom.xml +++ b/source/pom.xml @@ -35,7 +35,7 @@ - 0.3.0.RELEASE + 0.5.0-SNAPSHOT 1.2.0-SNAPSHOT 1.2.0-SNAPSHOT 2.4 diff --git a/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Invalid_Signer_Test_.java b/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Invalid_Signer_Test_.java deleted file mode 100644 index 00790ebe..00000000 --- a/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Invalid_Signer_Test_.java +++ /dev/null @@ -1,97 +0,0 @@ -/** - * Copyright: Copyright 2016-2020 JD.COM All Right Reserved - * FileName: test.com.jd.blockchain.sdk.test.SDK_GateWay_InsertData_Test - * Author: shaozhuguang - * Department: 区块链研发部 - * Date: 2018/9/4 上午11:06 - * Description: 插入数据测试 - */ -package test.com.jd.blockchain.sdk.test; - -import com.jd.blockchain.binaryproto.DataContractRegistry; -import com.jd.blockchain.crypto.*; -import com.jd.blockchain.ledger.*; -import com.jd.blockchain.sdk.BlockchainService; -import com.jd.blockchain.sdk.client.GatewayServiceFactory; -import com.jd.blockchain.transaction.TxResponseMessage; -import org.junit.Before; -import org.junit.Test; - -import static org.junit.Assert.assertTrue; - -/** - * 注册具有无效签名的用户账户 - * @author zhangshuang - * @create 2019/12/6 - * @since 1.0.0 - */ - -public class SDK_GateWay_Invalid_Signer_Test_ { - - private PrivKey privKey; - private PubKey pubKey; - - private BlockchainKeypair CLIENT_CERT = null; - - private String GATEWAY_IPADDR = null; - - private int GATEWAY_PORT; - - private boolean SECURE; - - private BlockchainService service; - - public static final String PASSWORD = "abc"; - - public static final String PUB_KEYS = "3snPdw7i7Pb3B5AxpSXy6YVruvftugNQ7rB7k2KWukhBwKQhFBFagT"; - public static final String PRIV_KEYS = "177gjtSgSdUF3LwRFGhzbpZZxmXXChsnwbuuLCG1V9KYfVuuxLwXGmZCp5FGUvsenhwBQLV"; - - @Before - public void init() { - - privKey = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS, PASSWORD); - pubKey = KeyGenUtils.decodePubKey(PUB_KEYS); - - CLIENT_CERT = new BlockchainKeypair(SDK_GateWay_KeyPair_Para.pubKey0, SDK_GateWay_KeyPair_Para.privkey0); - GATEWAY_IPADDR = "localhost"; - GATEWAY_PORT = 11000; - SECURE = false; - GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IPADDR, GATEWAY_PORT, SECURE, - CLIENT_CERT); - service = serviceFactory.getBlockchainService(); - - DataContractRegistry.register(TransactionContent.class); - DataContractRegistry.register(TransactionContentBody.class); - DataContractRegistry.register(TransactionRequest.class); - DataContractRegistry.register(NodeRequest.class); - DataContractRegistry.register(EndpointRequest.class); - DataContractRegistry.register(TransactionResponse.class); - } - - @Test - public void registerUser_Test() { - HashDigest[] ledgerHashs = service.getLedgerHashs(); - // 在本地定义注册账号的 TX; - TransactionTemplate txTemp = service.newTransaction(ledgerHashs[0]); - - //existed signer - AsymmetricKeypair keyPair = new BlockchainKeypair(pubKey, privKey); - - BlockchainKeypair user = BlockchainKeyGenerator.getInstance().generate(); - - // 注册 - txTemp.users().register(user.getIdentity()); - - // TX 准备就绪; - PreparedTransaction prepTx = txTemp.prepare(); - - // 使用私钥进行签名; - prepTx.sign(keyPair); - - // 提交交易; - TransactionResponse transactionResponse = prepTx.commit(); - - assertTrue(transactionResponse.getExecutionState().CODE == TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK.CODE); - - } -} \ No newline at end of file diff --git a/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Tx_RollBack_Test_.java b/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Tx_RollBack_Test_.java deleted file mode 100644 index 4c8c233b..00000000 --- a/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Tx_RollBack_Test_.java +++ /dev/null @@ -1,114 +0,0 @@ -package test.com.jd.blockchain.sdk.test; - -import com.jd.blockchain.binaryproto.DataContractRegistry; -import com.jd.blockchain.crypto.*; -import com.jd.blockchain.ledger.*; -import com.jd.blockchain.sdk.BlockchainService; -import com.jd.blockchain.sdk.client.GatewayServiceFactory; -import com.jd.blockchain.transaction.TxResponseMessage; -import org.junit.Before; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -//Transaction rollback test example -public class SDK_GateWay_Tx_RollBack_Test_ { - - private PrivKey privKey; - private PubKey pubKey; - - private BlockchainKeypair CLIENT_CERT = null; - - private String GATEWAY_IPADDR = null; - - private int GATEWAY_PORT; - - private boolean SECURE; - - private BlockchainService service; - - private BlockchainKeypair user; - - private BlockchainKeypair dataAccount; - - @Before - public void init() { - - privKey = SDK_GateWay_KeyPair_Para.privkey1; - pubKey = SDK_GateWay_KeyPair_Para.pubKey1; - - CLIENT_CERT = new BlockchainKeypair(SDK_GateWay_KeyPair_Para.pubKey0, SDK_GateWay_KeyPair_Para.privkey0); - GATEWAY_IPADDR = "127.0.0.1"; - GATEWAY_PORT = 11000; - SECURE = false; - GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IPADDR, GATEWAY_PORT, SECURE, - CLIENT_CERT); - service = serviceFactory.getBlockchainService(); - - DataContractRegistry.register(TransactionContent.class); - DataContractRegistry.register(TransactionContentBody.class); - DataContractRegistry.register(TransactionRequest.class); - DataContractRegistry.register(NodeRequest.class); - DataContractRegistry.register(EndpointRequest.class); - DataContractRegistry.register(TransactionResponse.class); - - user = BlockchainKeyGenerator.getInstance().generate(); - - dataAccount = BlockchainKeyGenerator.getInstance().generate(); - - } - - @Test - public void failedTxRollback_Test() { - - HashDigest[] ledgerHashs = service.getLedgerHashs(); - - //Construct the first transaction - TransactionTemplate txTemp = service.newTransaction(ledgerHashs[0]); - - AsymmetricKeypair keyPair = new BlockchainKeypair(pubKey, privKey); - - //Register user account - txTemp.users().register(user.getIdentity()); - - //Register data account - txTemp.dataAccounts().register(dataAccount.getIdentity()); - - String dataKey = "jd_code"; - String dataVal = "www.jd.com"; - - // Construct error kv version - txTemp.dataAccount(dataAccount.getAddress()).setText(dataKey, dataVal, 1); - - PreparedTransaction prepTx = txTemp.prepare(); - - prepTx.sign(keyPair); - - //Commit transaction - TransactionResponse transactionResponse = prepTx.commit(); - - //The first transaction will rollback, due to version error - assertEquals(transactionResponse.getExecutionState().CODE, TransactionState.DATA_VERSION_CONFLICT.CODE); - - //Construct the second transaction - TransactionTemplate txTemp1 = service.newTransaction(ledgerHashs[0]); - - txTemp1.users().register(user.getIdentity()); - - txTemp1.dataAccounts().register(dataAccount.getIdentity()); - - txTemp1.dataAccount(dataAccount.getAddress()).setText(dataKey, dataVal, -1); - - PreparedTransaction prepTx1 = txTemp1.prepare(); - - prepTx1.sign(keyPair); - - TransactionResponse transactionResponse1 = prepTx1.commit(); - - //The second transaction success - assertTrue(transactionResponse1.isSuccess()); - - } - -} diff --git a/source/test/test-integration/pom.xml b/source/test/test-integration/pom.xml index 37e3a382..87809a0c 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 795bdb26..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 @@ -14,6 +14,8 @@ import com.jd.blockchain.tools.initializer.LedgerBindingConfig; public class IntegratedContext { + private HashDigest ledgerHash; + private Map nodes = new HashMap<>(); public int[] getNodeIds() { @@ -27,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); } 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 219ca288..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,10 +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; @@ -24,10 +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.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; @@ -43,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(); @@ -62,7 +72,15 @@ public class IntegrationTest { private static String memDbConnString = LedgerInitConsensusConfig.memConnectionStrings[0]; - public static void main(String[] args) { + 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(); @@ -71,17 +89,30 @@ public class IntegrationTest { 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()); ThreadInvoker.AsyncCallback peerStarting0 = peer0.start(); ThreadInvoker.AsyncCallback peerStarting1 = peer1.start(); @@ -111,6 +142,17 @@ public class IntegrationTest { 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--------"); @@ -119,6 +161,59 @@ public class IntegrationTest { // 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); +// } /** * 检查所有节点之间的账本是否一致; * @@ -141,6 +236,83 @@ 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); @@ -148,6 +320,17 @@ public class IntegrationTest { ((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(); @@ -156,12 +339,74 @@ public class IntegrationTest { AsymmetricKeypair adminKey = context.getNode(0).getPartiKeyPair(); - BlockchainKeypair newUserAcount = testSDK_RegisterUser(adminKey, ledgerHashs[0], bcsrv, context); + // 注册用户,并验证最终写入; + 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); - ((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 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); } @@ -512,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()); 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/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/LedgerInitializeWebTest.java b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerInitializeWebTest.java index e31e015d..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,7 +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; @@ -28,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; @@ -341,7 +339,7 @@ public class LedgerInitializeWebTest { throw new IllegalStateException(e.getMessage(), e); } } - + public static Properties loadConsensusSetting(String configPath) { ClassPathResource ledgerInitSettingResource = new ClassPathResource(configPath); try (InputStream in = ledgerInitSettingResource.getInputStream()) { @@ -403,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); } @@ -446,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; } 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/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();