# Conflicts: # source/pom.xmltags/1.1.2^2
@@ -354,126 +354,75 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer | |||||
// }); | // }); | ||||
} | } | ||||
/** | |||||
* | |||||
* Used by consensus write phase, pre compute new block hash | |||||
* | |||||
*/ | |||||
// public BatchAppResultImpl preComputeAppHash(byte[][] commands) { | |||||
// String batchId = messageHandle.beginBatch(realmName); | |||||
// List<AsyncFuture<byte[]>> asyncFutureLinkedList = new ArrayList<>(commands.length); | |||||
// List<byte[]> responseLinkedList = new ArrayList<>(); | |||||
// try { | |||||
// int msgId = 0; | |||||
// for (byte[] txContent : commands) { | |||||
// AsyncFuture<byte[]> 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 | * Used by consensus write phase, pre compute new block hash | ||||
*/ | */ | ||||
public BatchAppResultImpl preComputeAppHash(byte[][] commands) { | public BatchAppResultImpl preComputeAppHash(byte[][] commands) { | ||||
String batchId = messageHandle.beginBatch(realmName); | |||||
List<AsyncFuture<byte[]>> asyncFutureLinkedList = new ArrayList<>(commands.length); | List<AsyncFuture<byte[]>> asyncFutureLinkedList = new ArrayList<>(commands.length); | ||||
List<byte[]> responseLinkedList = new ArrayList<>(); | List<byte[]> responseLinkedList = new ArrayList<>(); | ||||
BatchAppResultImpl result; | |||||
StateSnapshot newStateSnapshot = null; | |||||
StateSnapshot preStateSnapshot = null; | |||||
BatchAppResultImpl result = null; | |||||
String batchId = null; | |||||
int msgId = 0; | |||||
try { | try { | ||||
int msgId = 0; | |||||
boolean isOK = true; | |||||
TransactionState transactionState = TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK; | |||||
batchId = messageHandle.beginBatch(realmName); | |||||
preStateSnapshot = messageHandle.getStateSnapshot(realmName); | |||||
if (preStateSnapshot == null) { | |||||
throw new IllegalStateException("Pre block state snapshot is null!"); | |||||
} | |||||
for (int i = 0; i < commands.length; i++) { | for (int i = 0; i < commands.length; i++) { | ||||
byte[] txContent = commands[i]; | byte[] txContent = commands[i]; | ||||
try { | |||||
AsyncFuture<byte[]> asyncFuture = messageHandle.processOrdered(msgId++, txContent, realmName, batchId); | |||||
asyncFutureLinkedList.add(asyncFuture); | |||||
} catch (BlockRollbackException e) { | |||||
LOGGER.error("Error occurred while processing ordered messages! --" + e.getMessage(), e); | |||||
isOK = false; | |||||
// TODO: handle the BlockRollbackException in detail; | |||||
if (e instanceof DataVersionConflictException) { | |||||
transactionState = TransactionState.DATA_VERSION_CONFLICT; | |||||
} | |||||
break; | |||||
} | |||||
AsyncFuture<byte[]> asyncFuture = messageHandle.processOrdered(msgId++, txContent, realmName, batchId); | |||||
asyncFutureLinkedList.add(asyncFuture); | |||||
} | } | ||||
newStateSnapshot = messageHandle.completeBatch(realmName, batchId); | |||||
if (isOK) { | |||||
StateSnapshot stateSnapshot = messageHandle.completeBatch(realmName, batchId); | |||||
byte[] blockHashBytes = stateSnapshot.getSnapshot(); | |||||
for (int i = 0; i < asyncFutureLinkedList.size(); i++) { | |||||
responseLinkedList.add(asyncFutureLinkedList.get(i).get()); | |||||
} | |||||
result = new BatchAppResultImpl(responseLinkedList, blockHashBytes, batchId); | |||||
result.setErrorCode((byte) 0); | |||||
return result; | |||||
} else { | |||||
for (int i = 0; i < commands.length; i++) { | |||||
responseLinkedList.add(createAppResponse(commands[i],transactionState)); | |||||
} | |||||
Random random = new Random(); | |||||
byte[] rand = new byte[4]; | |||||
random.nextBytes(rand); | |||||
for (int i = 0; i < asyncFutureLinkedList.size(); i++) { | |||||
responseLinkedList.add(asyncFutureLinkedList.get(i).get()); | |||||
} | |||||
result = new BatchAppResultImpl(responseLinkedList, rand, batchId); | |||||
result.setErrorCode((byte) 1); | |||||
result = new BatchAppResultImpl(responseLinkedList, newStateSnapshot.getSnapshot(), batchId); | |||||
result.setErrorCode((byte) 0); | |||||
return result; | |||||
} catch (Exception e) { | |||||
LOGGER.error("Error occurred while pre compute app! --" + e.getMessage(), e); | |||||
for (int i = 0; i < commands.length; i++) { | |||||
responseLinkedList.add(createAppResponse(commands[i],TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK)); | |||||
} | } | ||||
} catch (Exception e) { | |||||
LOGGER.error("Error occurred while genearte batch app result! --" + e.getMessage(), e); | |||||
throw e; | |||||
result = new BatchAppResultImpl(responseLinkedList,preStateSnapshot.getSnapshot(), batchId); | |||||
result.setErrorCode((byte) 1); | |||||
} | } | ||||
return result; | |||||
} | } | ||||
public byte[] createAppResponse(byte[] command, TransactionState transactionState) { | |||||
// Block full rollback responses, generated in pre compute phase, due to tx exception | |||||
private byte[] createAppResponse(byte[] command, TransactionState transactionState) { | |||||
TransactionRequest txRequest = BinaryProtocol.decode(command); | TransactionRequest txRequest = BinaryProtocol.decode(command); | ||||
TxResponseMessage resp = new TxResponseMessage(txRequest.getTransactionContent().getHash()); | TxResponseMessage resp = new TxResponseMessage(txRequest.getTransactionContent().getHash()); | ||||
// resp.setExecutionState(TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK); | |||||
resp.setExecutionState(transactionState); | resp.setExecutionState(transactionState); | ||||
return BinaryProtocol.encode(resp, TransactionResponse.class); | return BinaryProtocol.encode(resp, TransactionResponse.class); | ||||
} | } | ||||
/** | |||||
* | |||||
* Consensus write phase will terminate, new block hash values are inconsistent, update batch messages execute state | |||||
* | |||||
*/ | |||||
//update batch messages to block full rollback state | |||||
public List<byte[]> updateAppResponses(List<byte[]> asyncResponseLinkedList) { | public List<byte[]> updateAppResponses(List<byte[]> asyncResponseLinkedList) { | ||||
List<byte[]> updatedResponses = new ArrayList<>(); | List<byte[]> updatedResponses = new ArrayList<>(); | ||||
for(int i = 0; i < asyncResponseLinkedList.size(); i++) { | for(int i = 0; i < asyncResponseLinkedList.size(); i++) { | ||||
TransactionResponse txResponse = BinaryProtocol.decode(asyncResponseLinkedList.get(i)); | TransactionResponse txResponse = BinaryProtocol.decode(asyncResponseLinkedList.get(i)); | ||||
TxResponseMessage resp = new TxResponseMessage(txResponse.getContentHash()); | TxResponseMessage resp = new TxResponseMessage(txResponse.getContentHash()); | ||||
resp.setExecutionState(TransactionState.IGNORED_BY_CONSENSUS_PHASE_PRECOMPUTE_ROLLBACK); | |||||
resp.setExecutionState(TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK); | |||||
updatedResponses.add(BinaryProtocol.encode(resp, TransactionResponse.class)); | updatedResponses.add(BinaryProtocol.encode(resp, TransactionResponse.class)); | ||||
} | } | ||||
@@ -486,9 +435,12 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer | |||||
* | * | ||||
*/ | */ | ||||
public void preComputeAppCommit(String batchId) { | public void preComputeAppCommit(String batchId) { | ||||
messageHandle.commitBatch(realmName, batchId); | |||||
try { | |||||
messageHandle.commitBatch(realmName, batchId); | |||||
} catch (BlockRollbackException e) { | |||||
LOGGER.error("Error occurred while pre compute commit --" + e.getMessage(), e); | |||||
throw e; | |||||
} | |||||
} | } | ||||
/** | /** | ||||
@@ -497,7 +449,7 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer | |||||
* | * | ||||
*/ | */ | ||||
public void preComputeAppRollback(String batchId) { | 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"); | LOGGER.debug("Rollback of operations that cause inconsistencies in the ledger"); | ||||
} | } | ||||
@@ -19,7 +19,8 @@ public class ConsensusProviders { | |||||
provider = providers.get(className); | provider = providers.get(className); | ||||
if (provider == null) { | if (provider == null) { | ||||
provider = loadProvider(ConsensusProvider.class, className); | provider = loadProvider(ConsensusProvider.class, className); | ||||
providers.put(className, provider); | |||||
// providers.put(className, provider); | |||||
registerProvider(provider); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -59,4 +59,12 @@ public interface MessageHandle { | |||||
*/ | */ | ||||
AsyncFuture<byte[]> processUnordered(byte[] message); | AsyncFuture<byte[]> processUnordered(byte[] message); | ||||
/** | |||||
* 获得当前最新区块的状态快照 | |||||
* | |||||
* @param realmName | |||||
* @return 最新区块的状态快照 | |||||
*/ | |||||
StateSnapshot getStateSnapshot(String realmName); | |||||
} | } |
@@ -374,6 +374,10 @@ class LedgerRepositoryImpl implements LedgerRepository { | |||||
return new LedgerDataset(adminDataset, userAccountSet, dataAccountSet, contractAccountSet, true); | return new LedgerDataset(adminDataset, userAccountSet, dataAccountSet, contractAccountSet, true); | ||||
} | } | ||||
public synchronized void resetNextBlockEditor() { | |||||
this.nextBlockEditor = null; | |||||
} | |||||
@Override | @Override | ||||
public synchronized LedgerEditor createNextBlock() { | public synchronized LedgerEditor createNextBlock() { | ||||
if (closed) { | if (closed) { | ||||
@@ -355,7 +355,11 @@ public class LedgerTransactionalEditor implements LedgerEditor { | |||||
throw new IllegalStateException("The current block is not ready yet!"); | 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; | committed = true; | ||||
} | } | ||||
@@ -39,6 +39,14 @@ public class TransactionBatchProcessor implements TransactionBatchProcess { | |||||
private TransactionBatchResult batchResult; | private TransactionBatchResult batchResult; | ||||
public byte[] getPrevLatestBlockHash() { | |||||
return ledger.getLatestBlockHash().toBytes(); | |||||
} | |||||
public long getPreLatestBlockHeight() { | |||||
return ledger.getLatestBlockHeight(); | |||||
} | |||||
public HashDigest getLedgerHash() { | public HashDigest getLedgerHash() { | ||||
return ledger.getHash(); | return ledger.getHash(); | ||||
} | } | ||||
@@ -273,9 +281,6 @@ public class TransactionBatchProcessor implements TransactionBatchProcess { | |||||
// rollback all the block; | // rollback all the block; | ||||
// TODO: handle the BlockRollbackException in detail; | // TODO: handle the BlockRollbackException in detail; | ||||
result = TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK; | result = TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK; | ||||
if (e instanceof DataVersionConflictException) { | |||||
result = TransactionState.DATA_VERSION_CONFLICT; | |||||
} | |||||
txCtx.rollback(); | txCtx.rollback(); | ||||
LOGGER.error( | LOGGER.error( | ||||
String.format("Transaction was rolled back! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s", | String.format("Transaction was rolled back! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s", | ||||
@@ -295,6 +300,8 @@ public class TransactionBatchProcessor implements TransactionBatchProcess { | |||||
result = TransactionState.CONTRACT_DOES_NOT_EXIST; | result = TransactionState.CONTRACT_DOES_NOT_EXIST; | ||||
} else if (e instanceof ParticipantDoesNotExistException) { | } else if (e instanceof ParticipantDoesNotExistException) { | ||||
result = TransactionState.PARTICIPANT_DOES_NOT_EXIST; | result = TransactionState.PARTICIPANT_DOES_NOT_EXIST; | ||||
} else if (e instanceof DataVersionConflictException) { | |||||
result = TransactionState.DATA_VERSION_CONFLICT; | |||||
} | } | ||||
txCtx.discardAndCommit(result, operationResults); | txCtx.discardAndCommit(result, operationResults); | ||||
LOGGER.error(String.format( | LOGGER.error(String.format( | ||||
@@ -48,6 +48,16 @@ public class TransactionEngineImpl implements TransactionEngine { | |||||
return batchs.get(ledgerHash); | 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) { | private void finishBatch(HashDigest ledgerHash) { | ||||
batchs.remove(ledgerHash); | batchs.remove(ledgerHash); | ||||
} | } | ||||
@@ -0,0 +1,188 @@ | |||||
package test.com.jd.blockchain.ledger.core; | |||||
import com.jd.blockchain.binaryproto.DataContractRegistry; | |||||
import com.jd.blockchain.crypto.HashDigest; | |||||
import com.jd.blockchain.ledger.*; | |||||
import com.jd.blockchain.ledger.core.*; | |||||
import com.jd.blockchain.storage.service.utils.MemoryKVStorage; | |||||
import org.junit.Test; | |||||
import org.mockito.Mockito; | |||||
import static org.junit.Assert.*; | |||||
import static org.junit.Assert.assertFalse; | |||||
import static org.junit.Assert.assertTrue; | |||||
import static org.mockito.Matchers.any; | |||||
import static org.mockito.Matchers.anyLong; | |||||
import static org.mockito.Mockito.doCallRealMethod; | |||||
import static org.mockito.Mockito.doThrow; | |||||
import static org.mockito.Mockito.when; | |||||
public class BlockFullRollBackTest { | |||||
static { | |||||
DataContractRegistry.register(TransactionContent.class); | |||||
DataContractRegistry.register(TransactionContentBody.class); | |||||
DataContractRegistry.register(TransactionRequest.class); | |||||
DataContractRegistry.register(NodeRequest.class); | |||||
DataContractRegistry.register(EndpointRequest.class); | |||||
DataContractRegistry.register(TransactionResponse.class); | |||||
DataContractRegistry.register(UserRegisterOperation.class); | |||||
DataContractRegistry.register(DataAccountRegisterOperation.class); | |||||
} | |||||
private static final String LEDGER_KEY_PREFIX = "LDG://"; | |||||
private HashDigest ledgerHash = null; | |||||
private BlockchainKeypair parti0 = BlockchainKeyGenerator.getInstance().generate(); | |||||
private BlockchainKeypair parti1 = BlockchainKeyGenerator.getInstance().generate(); | |||||
private BlockchainKeypair parti2 = BlockchainKeyGenerator.getInstance().generate(); | |||||
private BlockchainKeypair parti3 = BlockchainKeyGenerator.getInstance().generate(); | |||||
private BlockchainKeypair[] participants = { parti0, parti1, parti2, parti3 }; | |||||
@Test | |||||
public void testBlockFullkRollBack() { | |||||
final MemoryKVStorage STORAGE = new MemoryKVStorage(); | |||||
final MemoryKVStorage STORAGE_Mock = Mockito.spy(STORAGE); | |||||
// 初始化账本到指定的存储库; | |||||
ledgerHash = initLedger(STORAGE_Mock, parti0, parti1, parti2, parti3); | |||||
System.out.println("---------- Ledger init OK !!! ----------"); | |||||
// 加载账本; | |||||
LedgerManager ledgerManager = new LedgerManager(); | |||||
LedgerRepository ledgerRepo = ledgerManager.register(ledgerHash, STORAGE_Mock); | |||||
// 构造存储错误,并产生区块回滚 | |||||
doThrow(BlockRollbackException.class).when(STORAGE_Mock).set(any(), any(), anyLong()); | |||||
LedgerEditor newBlockEditor = ledgerRepo.createNextBlock(); | |||||
OperationHandleRegisteration opReg = new DefaultOperationHandleRegisteration(); | |||||
LedgerSecurityManager securityManager = getSecurityManager(); | |||||
TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(securityManager, newBlockEditor, | |||||
ledgerRepo, opReg); | |||||
// 注册新用户; | |||||
BlockchainKeypair userKeypair = BlockchainKeyGenerator.getInstance().generate(); | |||||
TransactionRequest transactionRequest = LedgerTestUtils.createTxRequest_UserReg(userKeypair, ledgerHash, | |||||
parti0, parti0); | |||||
TransactionResponse txResp = txbatchProcessor.schedule(transactionRequest); | |||||
LedgerBlock newBlock = newBlockEditor.prepare(); | |||||
try { | |||||
newBlockEditor.commit(); | |||||
} catch (BlockRollbackException e) { | |||||
newBlockEditor.cancel(); | |||||
} | |||||
// 验证正确性; | |||||
ledgerManager = new LedgerManager(); | |||||
ledgerRepo = ledgerManager.register(ledgerHash, STORAGE_Mock); | |||||
LedgerBlock latestBlock = ledgerRepo.getLatestBlock(); | |||||
assertEquals(ledgerRepo.getBlockHash(0), latestBlock.getHash()); | |||||
assertEquals(0, latestBlock.getHeight()); | |||||
LedgerDataQuery ledgerDS = ledgerRepo.getLedgerData(latestBlock); | |||||
boolean existUser = ledgerDS.getUserAccountSet().contains(userKeypair.getAddress()); | |||||
assertFalse(existUser); | |||||
doCallRealMethod().when(STORAGE_Mock).set(any(), any(), anyLong()); | |||||
//区块正常提交 | |||||
// 生成新区块; | |||||
LedgerEditor newBlockEditor1 = ledgerRepo.createNextBlock(); | |||||
OperationHandleRegisteration opReg1 = new DefaultOperationHandleRegisteration(); | |||||
LedgerSecurityManager securityManager1 = getSecurityManager(); | |||||
TransactionBatchProcessor txbatchProcessor1 = new TransactionBatchProcessor(securityManager1, newBlockEditor1, | |||||
ledgerRepo, opReg1); | |||||
// 注册新用户; | |||||
BlockchainKeypair userKeypair1 = BlockchainKeyGenerator.getInstance().generate(); | |||||
TransactionRequest transactionRequest1 = LedgerTestUtils.createTxRequest_UserReg(userKeypair1, ledgerHash, | |||||
parti0, parti0); | |||||
TransactionResponse txResp1 = txbatchProcessor1.schedule(transactionRequest1); | |||||
LedgerBlock newBlock1 = newBlockEditor1.prepare(); | |||||
try { | |||||
newBlockEditor1.commit(); | |||||
} catch (BlockRollbackException e) { | |||||
newBlockEditor1.cancel(); | |||||
} | |||||
ledgerManager = new LedgerManager(); | |||||
ledgerRepo = ledgerManager.register(ledgerHash, STORAGE_Mock); | |||||
LedgerBlock latestBlock1 = ledgerRepo.getLatestBlock(); | |||||
assertEquals(newBlock1.getHash(), latestBlock1.getHash()); | |||||
assertEquals(1, latestBlock1.getHeight()); | |||||
LedgerDataQuery ledgerDS1 = ledgerRepo.getLedgerData(latestBlock1); | |||||
boolean existUser1 = ledgerDS1.getUserAccountSet().contains(userKeypair1.getAddress()); | |||||
assertTrue(existUser1); | |||||
} | |||||
private static LedgerSecurityManager getSecurityManager() { | |||||
LedgerSecurityManager securityManager = Mockito.mock(LedgerSecurityManager.class); | |||||
SecurityPolicy securityPolicy = Mockito.mock(SecurityPolicy.class); | |||||
when(securityPolicy.isEndpointEnable(any(LedgerPermission.class), any())).thenReturn(true); | |||||
when(securityPolicy.isEndpointEnable(any(TransactionPermission.class), any())).thenReturn(true); | |||||
when(securityPolicy.isNodeEnable(any(LedgerPermission.class), any())).thenReturn(true); | |||||
when(securityPolicy.isNodeEnable(any(TransactionPermission.class), any())).thenReturn(true); | |||||
when(securityManager.createSecurityPolicy(any(), any())).thenReturn(securityPolicy); | |||||
return securityManager; | |||||
} | |||||
private HashDigest initLedger(MemoryKVStorage storage, BlockchainKeypair... partiKeys) { | |||||
// 创建初始化配置; | |||||
LedgerInitSetting initSetting = LedgerTestUtils.createLedgerInitSetting(partiKeys); | |||||
// 创建账本; | |||||
LedgerEditor ldgEdt = LedgerTransactionalEditor.createEditor(initSetting, LEDGER_KEY_PREFIX, storage, storage); | |||||
TransactionRequest genesisTxReq = LedgerTestUtils.createLedgerInitTxRequest(partiKeys); | |||||
LedgerTransactionContext genisisTxCtx = ldgEdt.newTransaction(genesisTxReq); | |||||
LedgerDataset ldgDS = genisisTxCtx.getDataset(); | |||||
for (int i = 0; i < partiKeys.length; i++) { | |||||
UserAccount userAccount = ldgDS.getUserAccountSet().register(partiKeys[i].getAddress(), | |||||
partiKeys[i].getPubKey()); | |||||
userAccount.setProperty("Name", "参与方-" + i, -1); | |||||
userAccount.setProperty("Share", "" + (10 + i), -1); | |||||
} | |||||
LedgerTransaction tx = genisisTxCtx.commit(TransactionState.SUCCESS); | |||||
assertEquals(genesisTxReq.getTransactionContent().getHash(), tx.getTransactionContent().getHash()); | |||||
assertEquals(0, tx.getBlockHeight()); | |||||
LedgerBlock block = ldgEdt.prepare(); | |||||
assertEquals(0, block.getHeight()); | |||||
assertNotNull(block.getHash()); | |||||
assertNull(block.getPreviousHash()); | |||||
// 创世区块的账本哈希为 null; | |||||
assertNull(block.getLedgerHash()); | |||||
assertNotNull(block.getHash()); | |||||
// 提交数据,写入存储; | |||||
ldgEdt.commit(); | |||||
HashDigest ledgerHash = block.getHash(); | |||||
return ledgerHash; | |||||
} | |||||
} |
@@ -372,7 +372,7 @@ public class TransactionBatchProcessorTest { | |||||
} catch (DataVersionConflictException e) { | } catch (DataVersionConflictException e) { | ||||
versionConflictionException = e; | versionConflictionException = e; | ||||
} | } | ||||
assertNotNull(versionConflictionException); | |||||
// assertNotNull(versionConflictionException); | |||||
newBlock = newBlockEditor.prepare(); | newBlock = newBlockEditor.prepare(); | ||||
newBlockEditor.commit(); | newBlockEditor.commit(); | ||||
@@ -1,6 +1,6 @@ | |||||
package com.jd.blockchain.ledger; | package com.jd.blockchain.ledger; | ||||
public class DataVersionConflictException extends BlockRollbackException { | |||||
public class DataVersionConflictException extends LedgerException { | |||||
private static final long serialVersionUID = 3583192000738807503L; | private static final long serialVersionUID = 3583192000738807503L; | ||||
@@ -169,7 +169,9 @@ public class PeerServerBooter { | |||||
app.addInitializers((ApplicationContextInitializer<ConfigurableApplicationContext>) applicationContext -> { | app.addInitializers((ApplicationContextInitializer<ConfigurableApplicationContext>) applicationContext -> { | ||||
ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory(); | ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory(); | ||||
for (Object bean : externalBeans) { | for (Object bean : externalBeans) { | ||||
beanFactory.registerSingleton(bean.toString(), bean); | |||||
if (bean != null) { | |||||
beanFactory.registerSingleton(bean.toString(), bean); | |||||
} | |||||
} | } | ||||
}); | }); | ||||
} | } | ||||
@@ -6,6 +6,8 @@ import com.jd.blockchain.ledger.OperationResult; | |||||
import com.jd.blockchain.ledger.TransactionRequest; | import com.jd.blockchain.ledger.TransactionRequest; | ||||
import com.jd.blockchain.ledger.TransactionResponse; | import com.jd.blockchain.ledger.TransactionResponse; | ||||
import com.jd.blockchain.ledger.TransactionState; | 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.TransactionBatchProcess; | ||||
import com.jd.blockchain.service.TransactionBatchResultHandle; | import com.jd.blockchain.service.TransactionBatchResultHandle; | ||||
import com.jd.blockchain.service.TransactionEngine; | 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.consensus.service.StateSnapshot; | ||||
import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
import javax.swing.plaf.nimbus.State; | |||||
import java.util.HashMap; | import java.util.HashMap; | ||||
import java.util.Map; | import java.util.Map; | ||||
import java.util.concurrent.ConcurrentHashMap; | import java.util.concurrent.ConcurrentHashMap; | ||||
@@ -61,6 +64,17 @@ public class ConsensusMessageDispatcher implements MessageHandle { | |||||
return realmProcessor.newBatchId(); | 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 | @Override | ||||
public AsyncFuture<byte[]> processOrdered(int messageId, byte[] message, String realmName, String batchId) { | public AsyncFuture<byte[]> processOrdered(int messageId, byte[] message, String realmName, String batchId) { | ||||
// TODO 要求messageId在同一个批次不重复,但目前暂不验证 | // TODO 要求messageId在同一个批次不重复,但目前暂不验证 | ||||
@@ -191,6 +205,10 @@ public class ConsensusMessageDispatcher implements MessageHandle { | |||||
return currBatchId; | return currBatchId; | ||||
} | } | ||||
public StateSnapshot getStateSnapshot() { | |||||
return new BlockStateSnapshot(((TransactionBatchProcessor)getTxBatchProcess()).getPreLatestBlockHeight(), ((TransactionBatchProcessor)getTxBatchProcess()).getPrevLatestBlockHash()); | |||||
} | |||||
public AsyncFuture<byte[]> schedule(TransactionRequest txRequest) { | public AsyncFuture<byte[]> schedule(TransactionRequest txRequest) { | ||||
CompletableAsyncFuture<byte[]> asyncTxResult = new CompletableAsyncFuture<>(); | CompletableAsyncFuture<byte[]> asyncTxResult = new CompletableAsyncFuture<>(); | ||||
TransactionResponse resp = getTxBatchProcess().schedule(txRequest); | TransactionResponse resp = getTxBatchProcess().schedule(txRequest); | ||||
@@ -236,6 +254,7 @@ public class ConsensusMessageDispatcher implements MessageHandle { | |||||
currBatchId = null; | currBatchId = null; | ||||
txResponseMap = null; | txResponseMap = null; | ||||
txBatchProcess = null; | txBatchProcess = null; | ||||
batchResultHandle =null; | |||||
} finally { | } finally { | ||||
realmLock.unlock(); | realmLock.unlock(); | ||||
} | } | ||||
@@ -244,10 +263,15 @@ public class ConsensusMessageDispatcher implements MessageHandle { | |||||
public void rollback(int reasonCode) { | public void rollback(int reasonCode) { | ||||
realmLock.lock(); | realmLock.lock(); | ||||
try { | try { | ||||
batchResultHandle.cancel(TransactionState.valueOf((byte)reasonCode)); | |||||
if (batchResultHandle != null) { | |||||
batchResultHandle.cancel(TransactionState.valueOf((byte)reasonCode)); | |||||
} | |||||
currBatchId = null; | currBatchId = null; | ||||
txResponseMap = null; | txResponseMap = null; | ||||
txBatchProcess = null; | txBatchProcess = null; | ||||
batchResultHandle = null; | |||||
((TransactionEngineImpl) (txEngine)).freeBatch(ledgerHash); | |||||
((TransactionEngineImpl) (txEngine)).resetNewBlockEditor(ledgerHash); | |||||
} finally { | } finally { | ||||
realmLock.unlock(); | realmLock.unlock(); | ||||
} | } | ||||
@@ -1,5 +1,6 @@ | |||||
package com.jd.blockchain.peer.ledger; | package com.jd.blockchain.peer.ledger; | ||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; | |||||
import org.springframework.context.annotation.Bean; | import org.springframework.context.annotation.Bean; | ||||
import org.springframework.context.annotation.Configuration; | import org.springframework.context.annotation.Configuration; | ||||
@@ -12,6 +13,7 @@ import com.jd.blockchain.service.TransactionEngine; | |||||
@Configuration | @Configuration | ||||
public class LedgerConfigurer { | public class LedgerConfigurer { | ||||
@ConditionalOnMissingBean | |||||
@Bean | @Bean | ||||
public LedgerManager ledgerManager() { | public LedgerManager ledgerManager() { | ||||
return new LedgerManager(); | return new LedgerManager(); | ||||
@@ -35,7 +35,7 @@ | |||||
</modules> | </modules> | ||||
<properties> | <properties> | ||||
<bft-smart.version>0.3.0.RELEASE</bft-smart.version> | |||||
<bft-smart.version>0.4.0.RELEASE</bft-smart.version> | |||||
<data-explorer.version>1.1.2.RELEASE</data-explorer.version> | <data-explorer.version>1.1.2.RELEASE</data-explorer.version> | ||||
<manager-explorer.version>1.1.2.RELEASE</manager-explorer.version> | <manager-explorer.version>1.1.2.RELEASE</manager-explorer.version> | ||||
<commons-io.version>2.4</commons-io.version> | <commons-io.version>2.4</commons-io.version> | ||||
@@ -58,6 +58,11 @@ | |||||
<version>${project.version}</version> | <version>${project.version}</version> | ||||
</dependency> | </dependency> | ||||
<dependency> | |||||
<groupId>org.mockito</groupId> | |||||
<artifactId>mockito-core</artifactId> | |||||
</dependency> | |||||
</dependencies> | </dependencies> | ||||
<build> | <build> | ||||
<plugins> | <plugins> | ||||
@@ -6,12 +6,16 @@ import java.util.Map; | |||||
import com.jd.blockchain.consensus.ConsensusSettings; | import com.jd.blockchain.consensus.ConsensusSettings; | ||||
import com.jd.blockchain.crypto.AsymmetricKeypair; | import com.jd.blockchain.crypto.AsymmetricKeypair; | ||||
import com.jd.blockchain.crypto.HashDigest; | |||||
import com.jd.blockchain.ledger.core.LedgerManager; | 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.storage.service.impl.composite.CompositeConnectionFactory; | ||||
import com.jd.blockchain.tools.initializer.LedgerBindingConfig; | import com.jd.blockchain.tools.initializer.LedgerBindingConfig; | ||||
public class IntegratedContext { | public class IntegratedContext { | ||||
private HashDigest ledgerHash; | |||||
private Map<Integer, Node> nodes = new HashMap<>(); | private Map<Integer, Node> nodes = new HashMap<>(); | ||||
public int[] getNodeIds() { | public int[] getNodeIds() { | ||||
@@ -25,6 +29,14 @@ public class IntegratedContext { | |||||
return ids; | return ids; | ||||
} | } | ||||
public HashDigest getLedgerHash() { | |||||
return ledgerHash; | |||||
} | |||||
public void setLedgerHash(HashDigest ledgerHash) { | |||||
this.ledgerHash = ledgerHash; | |||||
} | |||||
public Node getNode(int id) { | public Node getNode(int id) { | ||||
return nodes.get(id); | return nodes.get(id); | ||||
} | } | ||||
@@ -44,7 +56,7 @@ public class IntegratedContext { | |||||
private LedgerManager ledgerManager; | private LedgerManager ledgerManager; | ||||
private CompositeConnectionFactory storageDB; | |||||
private DbConnectionFactory storageDB; | |||||
private LedgerBindingConfig bindingConfig; | private LedgerBindingConfig bindingConfig; | ||||
@@ -60,7 +72,7 @@ public class IntegratedContext { | |||||
return ledgerManager; | return ledgerManager; | ||||
} | } | ||||
public CompositeConnectionFactory getStorageDB() { | |||||
public DbConnectionFactory getStorageDB() { | |||||
return storageDB; | return storageDB; | ||||
} | } | ||||
@@ -84,7 +96,7 @@ public class IntegratedContext { | |||||
this.ledgerManager = ledgerManager; | this.ledgerManager = ledgerManager; | ||||
} | } | ||||
public void setStorageDB(CompositeConnectionFactory storageDB) { | |||||
public void setStorageDB(DbConnectionFactory storageDB) { | |||||
this.storageDB = storageDB; | this.storageDB = storageDB; | ||||
} | } | ||||
@@ -7,7 +7,21 @@ import java.io.InputStream; | |||||
import java.util.Properties; | import java.util.Properties; | ||||
import java.util.Random; | import java.util.Random; | ||||
import java.util.concurrent.CountDownLatch; | 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 org.springframework.core.io.ClassPathResource; | ||||
import com.jd.blockchain.consensus.ConsensusProvider; | import com.jd.blockchain.consensus.ConsensusProvider; | ||||
@@ -21,24 +35,6 @@ import com.jd.blockchain.crypto.KeyGenUtils; | |||||
import com.jd.blockchain.crypto.PrivKey; | import com.jd.blockchain.crypto.PrivKey; | ||||
import com.jd.blockchain.crypto.PubKey; | import com.jd.blockchain.crypto.PubKey; | ||||
import com.jd.blockchain.gateway.GatewayConfigProperties.KeyPairConfig; | import com.jd.blockchain.gateway.GatewayConfigProperties.KeyPairConfig; | ||||
import com.jd.blockchain.ledger.BlockchainIdentity; | |||||
import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||||
import com.jd.blockchain.ledger.BlockchainKeypair; | |||||
import com.jd.blockchain.ledger.BytesValue; | |||||
import com.jd.blockchain.ledger.DataAccountKVSetOperation; | |||||
import com.jd.blockchain.ledger.TypedKVEntry; | |||||
import com.jd.blockchain.ledger.LedgerBlock; | |||||
import com.jd.blockchain.ledger.LedgerInfo; | |||||
import com.jd.blockchain.ledger.LedgerInitProperties; | |||||
import com.jd.blockchain.ledger.ParticipantNode; | |||||
import com.jd.blockchain.ledger.PreparedTransaction; | |||||
import com.jd.blockchain.ledger.TransactionResponse; | |||||
import com.jd.blockchain.ledger.TransactionTemplate; | |||||
import com.jd.blockchain.ledger.UserInfo; | |||||
import com.jd.blockchain.ledger.core.DataAccountQuery; | |||||
import com.jd.blockchain.ledger.core.LedgerManage; | |||||
import com.jd.blockchain.ledger.core.LedgerManager; | |||||
import com.jd.blockchain.ledger.core.LedgerQuery; | |||||
import com.jd.blockchain.sdk.BlockchainService; | import com.jd.blockchain.sdk.BlockchainService; | ||||
import com.jd.blockchain.sdk.client.GatewayServiceFactory; | import com.jd.blockchain.sdk.client.GatewayServiceFactory; | ||||
import com.jd.blockchain.storage.service.KVStorageService; | import com.jd.blockchain.storage.service.KVStorageService; | ||||
@@ -54,6 +50,9 @@ import test.com.jd.blockchain.intgr.IntegratedContext.Node; | |||||
import test.com.jd.blockchain.intgr.perf.LedgerInitializeWebTest; | import test.com.jd.blockchain.intgr.perf.LedgerInitializeWebTest; | ||||
import test.com.jd.blockchain.intgr.perf.Utils; | import test.com.jd.blockchain.intgr.perf.Utils; | ||||
import static org.mockito.Matchers.any; | |||||
import static org.mockito.Mockito.doAnswer; | |||||
public class IntegrationTest { | public class IntegrationTest { | ||||
// 合约测试使用的初始化数据; | // 合约测试使用的初始化数据; | ||||
BlockchainKeypair contractDataKey = BlockchainKeyGenerator.getInstance().generate(); | BlockchainKeypair contractDataKey = BlockchainKeyGenerator.getInstance().generate(); | ||||
@@ -73,37 +72,52 @@ public class IntegrationTest { | |||||
private static String memDbConnString = LedgerInitConsensusConfig.memConnectionStrings[0]; | private static String memDbConnString = LedgerInitConsensusConfig.memConnectionStrings[0]; | ||||
// private static final MQConnectionConfig mqConnConfig = new | |||||
// MQConnectionConfig(); | |||||
// static { | |||||
// mqConnConfig.setServer(MQ_SERVER); | |||||
// mqConnConfig.setTopic(MQ_TOPIC); | |||||
// } | |||||
private static AtomicBoolean isTestTurnOn = new AtomicBoolean(false); | |||||
public static final String PASSWORD = "abc"; | |||||
public static final String PUB_KEYS = "3snPdw7i7Pb3B5AxpSXy6YVruvftugNQ7rB7k2KWukhBwKQhFBFagT"; | |||||
public static final String PRIV_KEYS = "177gjtSgSdUF3LwRFGhzbpZZxmXXChsnwbuuLCG1V9KYfVuuxLwXGmZCp5FGUvsenhwBQLV"; | |||||
public static void main_(String[] args) { | public static void main_(String[] args) { | ||||
// init ledgers of all nodes ; | // init ledgers of all nodes ; | ||||
IntegratedContext context = initLedgers(); | IntegratedContext context = initLedgers(); | ||||
Node node0 = context.getNode(0); | Node node0 = context.getNode(0); | ||||
Node node1 = context.getNode(1); | Node node1 = context.getNode(1); | ||||
Node node2 = context.getNode(2); | Node node2 = context.getNode(2); | ||||
Node node3 = context.getNode(3); | 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); | 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); | 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); | 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); | NetworkAddress peerSrvAddr3 = new NetworkAddress("127.0.0.1", 10230); | ||||
PeerTestRunner peer3 = new PeerTestRunner(peerSrvAddr3, node3.getBindingConfig(), node3.getStorageDB()); | |||||
PeerTestRunner peer3 = new PeerTestRunner(peerSrvAddr3, node3.getBindingConfig(), node3.getStorageDB(), node3.getLedgerManager()); | |||||
AsyncCallback<Object> peerStarting0 = peer0.start(); | |||||
AsyncCallback<Object> peerStarting1 = peer1.start(); | |||||
AsyncCallback<Object> peerStarting2 = peer2.start(); | |||||
AsyncCallback<Object> peerStarting3 = peer3.start(); | |||||
ThreadInvoker.AsyncCallback<Object> peerStarting0 = peer0.start(); | |||||
ThreadInvoker.AsyncCallback<Object> peerStarting1 = peer1.start(); | |||||
ThreadInvoker.AsyncCallback<Object> peerStarting2 = peer2.start(); | |||||
ThreadInvoker.AsyncCallback<Object> peerStarting3 = peer3.start(); | |||||
peerStarting0.waitReturn(); | peerStarting0.waitReturn(); | ||||
peerStarting1.waitReturn(); | peerStarting1.waitReturn(); | ||||
@@ -116,38 +130,96 @@ public class IntegrationTest { | |||||
gwkey0.setPubKeyValue(LedgerInitializeWebTest.PUB_KEYS[0]); | gwkey0.setPubKeyValue(LedgerInitializeWebTest.PUB_KEYS[0]); | ||||
gwkey0.setPrivKeyValue(LedgerInitializeWebTest.PRIV_KEYS[0]); | gwkey0.setPrivKeyValue(LedgerInitializeWebTest.PRIV_KEYS[0]); | ||||
gwkey0.setPrivKeyPassword(encodedBase58Pwd); | 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<Object> gwStarting0 = gateway0.start(); | |||||
// AsyncCallback<Object> gwStarting1 = gateway1.start(); | |||||
ThreadInvoker.AsyncCallback<Object> gwStarting0 = gateway0.start(); | |||||
gwStarting0.waitReturn(); | gwStarting0.waitReturn(); | ||||
// gwStarting1.waitReturn(); | |||||
// 执行测试用例之前,校验每个节点的一致性; | // 执行测试用例之前,校验每个节点的一致性; | ||||
// testConsistencyAmongNodes(context); | |||||
// testConsistencyAmongNodes(context); | |||||
testStorageErrorBlockRollbackSdk(gateway0, context); | |||||
testConsensusFirstTimeoutSdk(gateway0, context); | |||||
testConsensusSecondTimeoutSdk(gateway0, context); | |||||
//todo | |||||
// testBlockHashInconsistentSdk(gateway0, context); | |||||
testTransactionRollbackSdk(gateway0, context); | |||||
testInvalidUserSignerSdk(gateway0, context); | |||||
testSDK(gateway0, context); | testSDK(gateway0, context); | ||||
System.out.println("------IntegrationTest Ok--------"); | |||||
// 执行测试用例之后,校验每个节点的一致性; | // 执行测试用例之后,校验每个节点的一致性; | ||||
// testConsistencyAmongNodes(context); | |||||
// testConsistencyAmongNodes(context); | |||||
} | } | ||||
//todo | |||||
// private static void mockNodeServer(IntegratedContext context) { | |||||
// | |||||
// Bytes nodeAddress0 = AddressEncoding.generateAddress(context.getNode(0).getPartiKeyPair().getPubKey()); | |||||
// Bytes nodeAddress1 = AddressEncoding.generateAddress(context.getNode(1).getPartiKeyPair().getPubKey()); | |||||
// Bytes nodeAddress2 = AddressEncoding.generateAddress(context.getNode(2).getPartiKeyPair().getPubKey()); | |||||
// Bytes nodeAddress3 = AddressEncoding.generateAddress(context.getNode(3).getPartiKeyPair().getPubKey()); | |||||
// | |||||
// BftsmartConsensusProvider bftsmartProvider0 = new BftsmartConsensusProvider(); | |||||
// BftsmartConsensusProvider mockedBftsmartProvider0 = Mockito.spy(bftsmartProvider0); | |||||
// | |||||
// BftsmartConsensusProvider bftsmartProvider1 = new BftsmartConsensusProvider(); | |||||
// BftsmartConsensusProvider mockedBftsmartProvider1 = Mockito.spy(bftsmartProvider1); | |||||
// | |||||
// BftsmartConsensusProvider bftsmartProvider2 = new BftsmartConsensusProvider(); | |||||
// BftsmartConsensusProvider mockedBftsmartProvider2 = Mockito.spy(bftsmartProvider2); | |||||
// | |||||
// BftsmartConsensusProvider bftsmartProvider3 = new BftsmartConsensusProvider(); | |||||
// BftsmartConsensusProvider mockedBftsmartProvider3 = Mockito.spy(bftsmartProvider3); | |||||
// | |||||
// doAnswer(new Answer<BftsmartNodeServer>() { | |||||
// @Override | |||||
// public BftsmartNodeServer answer(InvocationOnMock invocation) throws Throwable { | |||||
// BftsmartServerSettings serverSettings =(BftsmartServerSettings) invocation.getArguments()[0]; | |||||
// | |||||
// MessageHandle messageHandle = new ConsensusMessageDispatcher(); | |||||
// // mock spy messageHandle | |||||
// MessageHandle mockedMessageHandle = Mockito.spy(messageHandle); | |||||
// | |||||
// StateMachineReplicate stateMachineReplicate = new LedgerStateManager(); | |||||
// | |||||
// if(nodeAddress0.equals(serverSettings.getReplicaSettings().getAddress())){ | |||||
// doAnswer(new Answer() { | |||||
// @Override | |||||
// public Object answer(InvocationOnMock invocation) throws Throwable { | |||||
// | |||||
// if (isTestTurnOn.get()) { | |||||
// Random random = new Random(); | |||||
// byte[] msg = new byte[4]; | |||||
// random.nextBytes(msg); | |||||
// invocation.getArguments()[0] = msg; | |||||
// } | |||||
// return invocation.callRealMethod(); | |||||
// } | |||||
// }).when(mockedMessageHandle).processOrdered(any(), any(), any(), any()); | |||||
// } | |||||
// | |||||
// return new BftsmartNodeServer(serverSettings, mockedMessageHandle, stateMachineReplicate); | |||||
// } | |||||
// }).when(mockedBftsmartProvider0).getServerFactory().setupServer(any(), any(), any()); | |||||
// | |||||
// ConsensusProviders.registerProvider(mockedBftsmartProvider0); | |||||
// } | |||||
/** | /** | ||||
* 检查所有节点之间的账本是否一致; | * 检查所有节点之间的账本是否一致; | ||||
* | * | ||||
* @param context | * @param context | ||||
*/ | */ | ||||
private void testConsistencyAmongNodes(IntegratedContext context) { | |||||
private static void testConsistencyAmongNodes(IntegratedContext context) { | |||||
int[] ids = context.getNodeIds(); | int[] ids = context.getNodeIds(); | ||||
Node[] nodes = new Node[ids.length]; | Node[] nodes = new Node[ids.length]; | ||||
LedgerQuery[] ledgers = new LedgerQuery[ids.length]; | LedgerQuery[] ledgers = new LedgerQuery[ids.length]; | ||||
@@ -164,6 +236,180 @@ public class IntegrationTest { | |||||
} | } | ||||
} | } | ||||
private static void testConsensusFirstTimeoutSdk(GatewayTestRunner gateway, IntegratedContext context) { | |||||
AtomicBoolean isTestTurnOn = new AtomicBoolean(true); | |||||
Node node0 = context.getNode(0); | |||||
Node node1 = context.getNode(1); | |||||
LedgerManager ledgerManagerMock0 = node0.getLedgerManager(); | |||||
LedgerManager ledgerManagerMock1 = node1.getLedgerManager(); | |||||
doAnswer(new Answer<LedgerRepository>() { | |||||
@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<LedgerRepository>() { | |||||
@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<LedgerRepository>() { | |||||
@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<LedgerRepository>() { | |||||
@Override | |||||
public LedgerRepository answer(InvocationOnMock invocation) throws Throwable { | |||||
if (isTestTurnOn.get()) { | |||||
Thread.sleep(10000); | |||||
} | |||||
return (LedgerRepository)invocation.callRealMethod(); | |||||
} | |||||
}).when(ledgerManagerMock1).getLedger(any()); | |||||
testSDK(gateway, context); | |||||
isTestTurnOn.set(false); | |||||
} | |||||
//todo | |||||
// private static void testBlockHashInconsistentSdk(GatewayTestRunner gateway, IntegratedContext context) { | |||||
// isTestTurnOn.set(true); | |||||
// testSDK(gateway, context); | |||||
// isTestTurnOn.set(false); | |||||
// | |||||
// } | |||||
private static void testStorageErrorBlockRollbackSdk(GatewayTestRunner gateway, IntegratedContext context) { | |||||
((TestDbFactory)context.getNode(0).getStorageDB()).setErrorSetTurnOn(true); | |||||
((TestDbFactory)context.getNode(1).getStorageDB()).setErrorSetTurnOn(true); | |||||
((TestDbFactory)context.getNode(2).getStorageDB()).setErrorSetTurnOn(true); | |||||
((TestDbFactory)context.getNode(3).getStorageDB()).setErrorSetTurnOn(true); | |||||
testSDK(gateway, context); | |||||
((TestDbFactory)context.getNode(0).getStorageDB()).setErrorSetTurnOn(false); | |||||
((TestDbFactory)context.getNode(1).getStorageDB()).setErrorSetTurnOn(false); | |||||
((TestDbFactory)context.getNode(2).getStorageDB()).setErrorSetTurnOn(false); | |||||
((TestDbFactory)context.getNode(3).getStorageDB()).setErrorSetTurnOn(false); | |||||
} | |||||
private static void testTransactionRollbackSdk(GatewayTestRunner gateway, IntegratedContext context) { | |||||
// 连接网关; | |||||
GatewayServiceFactory gwsrvFact = GatewayServiceFactory.connect(gateway.getServiceAddress()); | |||||
BlockchainService bcsrv = gwsrvFact.getBlockchainService(); | |||||
HashDigest[] ledgerHashs = bcsrv.getLedgerHashs(); | |||||
AsymmetricKeypair adminKey = context.getNode(0).getPartiKeyPair(); | |||||
// 注册用户,并验证最终写入; | |||||
BlockchainKeypair dataAccount = BlockchainKeyGenerator.getInstance().generate(); | |||||
// 定义交易; | |||||
TransactionTemplate txTpl = bcsrv.newTransaction(ledgerHashs[0]); | |||||
txTpl.dataAccounts().register(dataAccount.getIdentity()); | |||||
String dataKey = "jd_code"; | |||||
String dataVal = "www.jd.com"; | |||||
// Construct error kv version | |||||
txTpl.dataAccount(dataAccount.getAddress()).setText(dataKey, dataVal, 1); | |||||
PreparedTransaction prepTx = txTpl.prepare(); | |||||
prepTx.sign(adminKey); | |||||
// 提交并等待共识返回; | |||||
TransactionResponse txResp = prepTx.commit(); | |||||
// 验证结果; | |||||
Node node0 = context.getNode(0); | |||||
LedgerManage ledgerManager = new LedgerManager(); | |||||
KVStorageService storageService = node0.getStorageDB().connect(memDbConnString).getStorageService(); | |||||
LedgerQuery ledgerOfNode0 = ledgerManager.register(ledgerHashs[0], storageService); | |||||
} | |||||
private static void testInvalidUserSignerSdk(GatewayTestRunner gateway, IntegratedContext context) { | |||||
// 连接网关; | |||||
GatewayServiceFactory gwsrvFact = GatewayServiceFactory.connect(gateway.getServiceAddress()); | |||||
BlockchainService bcsrv = gwsrvFact.getBlockchainService(); | |||||
HashDigest[] ledgerHashs = bcsrv.getLedgerHashs(); | |||||
//Invalid signer | |||||
PrivKey privKey = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS, PASSWORD); | |||||
PubKey pubKey = KeyGenUtils.decodePubKey(PUB_KEYS); | |||||
AsymmetricKeypair asymmetricKeypair = new AsymmetricKeypair(pubKey, privKey); | |||||
// 注册用户,并验证最终写入; | |||||
BlockchainKeypair user = BlockchainKeyGenerator.getInstance().generate(); | |||||
// 定义交易; | |||||
TransactionTemplate txTpl = bcsrv.newTransaction(ledgerHashs[0]); | |||||
txTpl.users().register(user.getIdentity()); | |||||
// 签名; | |||||
PreparedTransaction ptx = txTpl.prepare(); | |||||
HashDigest transactionHash = ptx.getHash(); | |||||
ptx.sign(asymmetricKeypair); | |||||
// 提交并等待共识返回; | |||||
TransactionResponse txResp = ptx.commit(); | |||||
// 验证结果; | |||||
Node node0 = context.getNode(0); | |||||
LedgerManage ledgerManager = new LedgerManager(); | |||||
KVStorageService storageService = node0.getStorageDB().connect(memDbConnString).getStorageService(); | |||||
LedgerQuery ledgerOfNode0 = ledgerManager.register(ledgerHashs[0], storageService); | |||||
} | |||||
private static void testSDK(GatewayTestRunner gateway, IntegratedContext context) { | private static void testSDK(GatewayTestRunner gateway, IntegratedContext context) { | ||||
// 连接网关; | // 连接网关; | ||||
GatewayServiceFactory gwsrvFact = GatewayServiceFactory.connect(gateway.getServiceAddress()); | GatewayServiceFactory gwsrvFact = GatewayServiceFactory.connect(gateway.getServiceAddress()); | ||||
@@ -427,15 +673,15 @@ public class IntegrationTest { | |||||
return; | 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() { | private static IntegratedContext initLedgers() { | ||||
Prompter consolePrompter = new PresetAnswerPrompter("N"); // new ConsolePrompter(); | Prompter consolePrompter = new PresetAnswerPrompter("N"); // new ConsolePrompter(); | ||||
LedgerInitProperties initSetting = loadInitSetting_integration(); | 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() | ConsensusSettings csProps = csProvider.getSettingsFactory() | ||||
.getConsensusSettingsBuilder() | .getConsensusSettingsBuilder() | ||||
.createSettings(props, Utils.loadParticipantNodes()); | .createSettings(props, Utils.loadParticipantNodes()); | ||||
@@ -465,29 +711,39 @@ public class IntegrationTest { | |||||
CountDownLatch quitLatch = new CountDownLatch(4); | CountDownLatch quitLatch = new CountDownLatch(4); | ||||
TestDbFactory dbFactory0 = new TestDbFactory(new CompositeConnectionFactory()); | |||||
dbFactory0.setErrorSetTurnOn(false); | |||||
DBConnectionConfig testDb0 = new DBConnectionConfig(); | DBConnectionConfig testDb0 = new DBConnectionConfig(); | ||||
testDb0.setConnectionUri("memory://local/0"); | testDb0.setConnectionUri("memory://local/0"); | ||||
LedgerBindingConfig bindingConfig0 = new LedgerBindingConfig(); | LedgerBindingConfig bindingConfig0 = new LedgerBindingConfig(); | ||||
AsyncCallback<HashDigest> callback0 = nodeCtx0.startInitCommand(privkey0, encodedPassword, initSetting, csProps, | AsyncCallback<HashDigest> 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(); | DBConnectionConfig testDb1 = new DBConnectionConfig(); | ||||
testDb1.setConnectionUri("memory://local/1"); | testDb1.setConnectionUri("memory://local/1"); | ||||
LedgerBindingConfig bindingConfig1 = new LedgerBindingConfig(); | LedgerBindingConfig bindingConfig1 = new LedgerBindingConfig(); | ||||
AsyncCallback<HashDigest> callback1 = nodeCtx1.startInitCommand(privkey1, encodedPassword, initSetting, csProps, | AsyncCallback<HashDigest> 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(); | DBConnectionConfig testDb2 = new DBConnectionConfig(); | ||||
testDb2.setConnectionUri("memory://local/2"); | testDb2.setConnectionUri("memory://local/2"); | ||||
LedgerBindingConfig bindingConfig2 = new LedgerBindingConfig(); | LedgerBindingConfig bindingConfig2 = new LedgerBindingConfig(); | ||||
AsyncCallback<HashDigest> callback2 = nodeCtx2.startInitCommand(privkey2, encodedPassword, initSetting, csProps, | AsyncCallback<HashDigest> 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(); | DBConnectionConfig testDb3 = new DBConnectionConfig(); | ||||
testDb3.setConnectionUri("memory://local/3"); | testDb3.setConnectionUri("memory://local/3"); | ||||
LedgerBindingConfig bindingConfig3 = new LedgerBindingConfig(); | LedgerBindingConfig bindingConfig3 = new LedgerBindingConfig(); | ||||
AsyncCallback<HashDigest> callback3 = nodeCtx3.startInitCommand(privkey3, encodedPassword, initSetting, csProps, | AsyncCallback<HashDigest> callback3 = nodeCtx3.startInitCommand(privkey3, encodedPassword, initSetting, csProps, | ||||
csProvider, testDb3, consolePrompter, bindingConfig3, quitLatch); | |||||
csProvider, testDb3, consolePrompter, bindingConfig3, quitLatch, dbFactory3); | |||||
HashDigest ledgerHash0 = callback0.waitReturn(); | HashDigest ledgerHash0 = callback0.waitReturn(); | ||||
HashDigest ledgerHash1 = callback1.waitReturn(); | HashDigest ledgerHash1 = callback1.waitReturn(); | ||||
@@ -501,6 +757,8 @@ public class IntegrationTest { | |||||
IntegratedContext context = new IntegratedContext(); | IntegratedContext context = new IntegratedContext(); | ||||
context.setLedgerHash(ledgerHash0); | |||||
Node node0 = new Node(0); | Node node0 = new Node(0); | ||||
node0.setConsensusSettings(csProps); | node0.setConsensusSettings(csProps); | ||||
node0.setLedgerManager(nodeCtx0.getLedgerManager()); | node0.setLedgerManager(nodeCtx0.getLedgerManager()); | ||||
@@ -542,7 +800,7 @@ public class IntegrationTest { | |||||
} | } | ||||
public static LedgerInitProperties loadInitSetting_integration() { | 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()) { | try (InputStream in = ledgerInitSettingResource.getInputStream()) { | ||||
LedgerInitProperties setting = LedgerInitProperties.resolve(in); | LedgerInitProperties setting = LedgerInitProperties.resolve(in); | ||||
return setting; | return setting; | ||||
@@ -1,5 +1,6 @@ | |||||
package test.com.jd.blockchain.intgr; | package test.com.jd.blockchain.intgr; | ||||
import com.jd.blockchain.ledger.core.LedgerManager; | |||||
import com.jd.blockchain.peer.PeerServerBooter; | import com.jd.blockchain.peer.PeerServerBooter; | ||||
import com.jd.blockchain.storage.service.DbConnectionFactory; | import com.jd.blockchain.storage.service.DbConnectionFactory; | ||||
import com.jd.blockchain.tools.initializer.LedgerBindingConfig; | import com.jd.blockchain.tools.initializer.LedgerBindingConfig; | ||||
@@ -28,18 +29,18 @@ public class PeerTestRunner { | |||||
} | } | ||||
public PeerTestRunner(NetworkAddress serviceAddress, LedgerBindingConfig ledgerBindingConfig) { | public PeerTestRunner(NetworkAddress serviceAddress, LedgerBindingConfig ledgerBindingConfig) { | ||||
this(serviceAddress, ledgerBindingConfig, null); | |||||
this(serviceAddress, ledgerBindingConfig, null, null); | |||||
} | } | ||||
public PeerTestRunner(NetworkAddress serviceAddress, LedgerBindingConfig ledgerBindingConfig, | public PeerTestRunner(NetworkAddress serviceAddress, LedgerBindingConfig ledgerBindingConfig, | ||||
DbConnectionFactory dbConnectionFactory) { | |||||
DbConnectionFactory dbConnectionFactory, LedgerManager ledgerManager) { | |||||
this.serviceAddress = serviceAddress; | this.serviceAddress = serviceAddress; | ||||
this.ledgerBindingConfig = ledgerBindingConfig; | this.ledgerBindingConfig = ledgerBindingConfig; | ||||
if (dbConnectionFactory == null) { | if (dbConnectionFactory == null) { | ||||
this.peerServer = new PeerServerBooter(ledgerBindingConfig, serviceAddress.getHost(), serviceAddress.getPort(),null); | this.peerServer = new PeerServerBooter(ledgerBindingConfig, serviceAddress.getHost(), serviceAddress.getPort(),null); | ||||
}else { | }else { | ||||
this.peerServer = new PeerServerBooter(ledgerBindingConfig, serviceAddress.getHost(), serviceAddress.getPort(),null, | this.peerServer = new PeerServerBooter(ledgerBindingConfig, serviceAddress.getHost(), serviceAddress.getPort(),null, | ||||
dbConnectionFactory); | |||||
dbConnectionFactory, ledgerManager); | |||||
} | } | ||||
} | } | ||||
@@ -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<ExPolicyKVStorage> exKVStorageMockedAnswer = new Answer<ExPolicyKVStorage>() { | |||||
@Override | |||||
public ExPolicyKVStorage answer(InvocationOnMock invocation) throws Throwable { | |||||
ExPolicyKVStorage reallyExKVStorage = (ExPolicyKVStorage) invocation.callRealMethod(); | |||||
ExPolicyKVStorage mockExKVStorage = Mockito.spy(reallyExKVStorage); | |||||
//按条件开关触发异常; | |||||
doAnswer(new Answer<Boolean>() { | |||||
@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<VersioningKVStorage> verKVStorageMockedAnswer = new Answer<VersioningKVStorage>() { | |||||
@Override | |||||
public VersioningKVStorage answer(InvocationOnMock invocation) throws Throwable { | |||||
VersioningKVStorage reallyVerKVStorage = (VersioningKVStorage) invocation.callRealMethod(); | |||||
VersioningKVStorage mockVerKVStorage = Mockito.spy(reallyVerKVStorage); | |||||
//按条件开关触发异常; | |||||
doAnswer(new Answer<Long>() { | |||||
@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<KVStorageService> storageMockedAnswer = new Answer<KVStorageService>() { | |||||
@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);; | |||||
} | |||||
} |
@@ -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; | |||||
} | |||||
} |
@@ -69,16 +69,16 @@ public class ConsensusTest { | |||||
Node node3 = context.getNode(3); | Node node3 = context.getNode(3); | ||||
NetworkAddress peerSrvAddr0 = new NetworkAddress("127.0.0.1", 10200); | 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); | 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); | 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); | 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<Object> peerStarting0 = peer0.start(); | AsyncCallback<Object> peerStarting0 = peer0.start(); | ||||
AsyncCallback<Object> peerStarting1 = peer1.start(); | AsyncCallback<Object> peerStarting1 = peer1.start(); | ||||
@@ -67,16 +67,16 @@ public class GlobalPerformanceTest { | |||||
Node node3 = context.getNode(3); | Node node3 = context.getNode(3); | ||||
NetworkAddress peerSrvAddr0 = new NetworkAddress("127.0.0.1", 10200); | 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); | 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); | 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); | 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<Object> peerStarting0 = peer0.start(); | AsyncCallback<Object> peerStarting0 = peer0.start(); | ||||
AsyncCallback<Object> peerStarting1 = peer1.start(); | AsyncCallback<Object> peerStarting1 = peer1.start(); | ||||
@@ -48,16 +48,17 @@ public class LedgerInitializeTest { | |||||
public static final String PASSWORD = "abc"; | 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 = { | public static final String[] PRIV_KEYS = { | ||||
"177gjsj5PHeCpbAtJE7qnbmhuZMHAEKuMsd45zHkv8F8AWBvTBbff8yRKdCyT3kwrmAjSnY", | |||||
"177gjw9u84WtuCsK8u2WeH4nWqzgEoJWY7jJF9AU6XwLHSosrcNX3H6SSBsfvR53HgX7KR2", | |||||
"177gk2FpjufgEon92mf2oRRFXDBZkRy8SkFci7Jxc5pApZEJz3oeCoxieWatDD3Xg7i1QEN", | |||||
"177gjvv7qvfCAXroFezSn23UFXLVLFofKS3y6DXkJ2DwVWS4LcRNtxRgiqWmQEeWNz4KQ3J" }; | |||||
"177gjzHTznYdPgWqZrH43W3yp37onm74wYXT4v9FukpCHBrhRysBBZh7Pzdo5AMRyQGJD7x", | |||||
"177gju9p5zrNdHJVEQnEEKF4ZjDDYmAXyfG84V5RPGVc5xFfmtwnHA7j51nyNLUFffzz5UT", | |||||
"177gjtwLgmSx5v1hFb46ijh7L9kdbKUpJYqdKVf9afiEmAuLgo8Rck9yu5UuUcHknWJuWaF", | |||||
"177gk1pudweTq5zgJTh8y3ENCTwtSFsKyX7YnpuKPo7rKgCkCBXVXh5z2syaTCPEMbuWRns" }; | |||||
private Map<NetworkAddress, LedgerInitConsensusService> serviceRegisterMap = new ConcurrentHashMap<>(); | private Map<NetworkAddress, LedgerInitConsensusService> serviceRegisterMap = new ConcurrentHashMap<>(); | ||||
@@ -5,6 +5,11 @@ import java.io.InputStream; | |||||
import java.util.Properties; | import java.util.Properties; | ||||
import java.util.concurrent.CountDownLatch; | 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.boot.SpringApplication; | ||||
import org.springframework.context.ConfigurableApplicationContext; | import org.springframework.context.ConfigurableApplicationContext; | ||||
import org.springframework.core.io.ClassPathResource; | import org.springframework.core.io.ClassPathResource; | ||||
@@ -27,12 +32,6 @@ import com.jd.blockchain.ledger.LedgerInitProperties; | |||||
import com.jd.blockchain.ledger.Operation; | import com.jd.blockchain.ledger.Operation; | ||||
import com.jd.blockchain.ledger.TransactionContent; | import com.jd.blockchain.ledger.TransactionContent; | ||||
import com.jd.blockchain.ledger.UserRegisterOperation; | 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.DbConnection; | ||||
import com.jd.blockchain.storage.service.impl.composite.CompositeConnectionFactory; | import com.jd.blockchain.storage.service.impl.composite.CompositeConnectionFactory; | ||||
//import com.jd.blockchain.storage.service.utils.MemoryBasedDb; | //import com.jd.blockchain.storage.service.utils.MemoryBasedDb; | ||||
@@ -52,6 +51,7 @@ import com.jd.blockchain.utils.io.BytesUtils; | |||||
import com.jd.blockchain.utils.io.FileUtils; | import com.jd.blockchain.utils.io.FileUtils; | ||||
import com.jd.blockchain.utils.net.NetworkAddress; | import com.jd.blockchain.utils.net.NetworkAddress; | ||||
import test.com.jd.blockchain.intgr.LedgerInitConsensusConfig; | |||||
import test.com.jd.blockchain.intgr.PresetAnswerPrompter; | import test.com.jd.blockchain.intgr.PresetAnswerPrompter; | ||||
public class LedgerInitializeWebTest { | public class LedgerInitializeWebTest { | ||||
@@ -73,7 +73,7 @@ public class LedgerInitializeWebTest { | |||||
// 加载初始化配置; | // 加载初始化配置; | ||||
LedgerInitProperties initSetting = loadInitSetting_1(); | LedgerInitProperties initSetting = loadInitSetting_1(); | ||||
// 加载共识配置; | // 加载共识配置; | ||||
Properties props = loadConsensusSetting(); | |||||
Properties props = loadConsensusSetting(LedgerInitConsensusConfig.bftsmartConfig.getConfigPath()); | |||||
// ConsensusProperties csProps = new ConsensusProperties(props); | // ConsensusProperties csProps = new ConsensusProperties(props); | ||||
ConsensusProvider csProvider = getConsensusProvider(); | ConsensusProvider csProvider = getConsensusProvider(); | ||||
ConsensusSettings csProps = csProvider.getSettingsFactory() | ConsensusSettings csProps = csProvider.getSettingsFactory() | ||||
@@ -242,7 +242,7 @@ public class LedgerInitializeWebTest { | |||||
Prompter consolePrompter = new PresetAnswerPrompter("N"); // new ConsolePrompter(); | Prompter consolePrompter = new PresetAnswerPrompter("N"); // new ConsolePrompter(); | ||||
LedgerInitProperties initSetting = loadInitSetting_2(); | LedgerInitProperties initSetting = loadInitSetting_2(); | ||||
Properties props = loadConsensusSetting(); | |||||
Properties props = loadConsensusSetting(LedgerInitConsensusConfig.bftsmartConfig.getConfigPath()); | |||||
// ConsensusProperties csProps = new ConsensusProperties(props); | // ConsensusProperties csProps = new ConsensusProperties(props); | ||||
ConsensusProvider csProvider = getConsensusProvider(); | ConsensusProvider csProvider = getConsensusProvider(); | ||||
ConsensusSettings csProps = csProvider.getSettingsFactory() | ConsensusSettings csProps = csProvider.getSettingsFactory() | ||||
@@ -340,8 +340,8 @@ public class LedgerInitializeWebTest { | |||||
} | } | ||||
} | } | ||||
public static Properties loadConsensusSetting() { | |||||
ClassPathResource ledgerInitSettingResource = new ClassPathResource("bftsmart.config"); | |||||
public static Properties loadConsensusSetting(String configPath) { | |||||
ClassPathResource ledgerInitSettingResource = new ClassPathResource(configPath); | |||||
try (InputStream in = ledgerInitSettingResource.getInputStream()) { | try (InputStream in = ledgerInitSettingResource.getInputStream()) { | ||||
return FileUtils.readProperties(in); | return FileUtils.readProperties(in); | ||||
} catch (IOException e) { | } catch (IOException e) { | ||||
@@ -365,7 +365,7 @@ public class LedgerInitializeWebTest { | |||||
private volatile LedgerManager ledgerManager; | private volatile LedgerManager ledgerManager; | ||||
private volatile CompositeConnectionFactory db; | |||||
private volatile DbConnectionFactory db; | |||||
private int id; | private int id; | ||||
@@ -401,9 +401,14 @@ public class LedgerInitializeWebTest { | |||||
// dbConnConfig.getPassword()); | // dbConnConfig.getPassword()); | ||||
DbConnection conn = db.connect(dbConnConfig.getUri()); | DbConnection conn = db.connect(dbConnConfig.getUri()); | ||||
LedgerQuery ledgerRepo = ledgerManager.register(ledgerHash, conn.getStorageService()); | LedgerQuery ledgerRepo = ledgerManager.register(ledgerHash, conn.getStorageService()); | ||||
return ledgerRepo; | return ledgerRepo; | ||||
} | } | ||||
public LedgerRepository ledgerRepository(HashDigest ledgerHash) { | |||||
return ledgerManager.getLedger(ledgerHash); | |||||
} | |||||
public SignatureDigest createPermissionRequestSignature(int requesterId, PrivKey privKey) { | public SignatureDigest createPermissionRequestSignature(int requesterId, PrivKey privKey) { | ||||
return controller.signPermissionRequest(requesterId, privKey); | return controller.signPermissionRequest(requesterId, privKey); | ||||
} | } | ||||
@@ -429,21 +434,14 @@ public class LedgerInitializeWebTest { | |||||
return invoker.start(); | return invoker.start(); | ||||
} | } | ||||
// public AsyncCallback<HashDigest> 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<HashDigest> startInitCommand(PrivKey privKey, String base58Pwd, | public AsyncCallback<HashDigest> 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.dbConnConfig = dbConnConfig; | ||||
// this.mqConnConfig = mqConnConfig; | // this.mqConnConfig = mqConnConfig; | ||||
this.db = db; | |||||
ThreadInvoker<HashDigest> invoker = new ThreadInvoker<HashDigest>() { | ThreadInvoker<HashDigest> invoker = new ThreadInvoker<HashDigest>() { | ||||
@Override | @Override | ||||
@@ -451,7 +449,11 @@ public class LedgerInitializeWebTest { | |||||
LedgerInitCommand initCmd = new LedgerInitCommand(); | LedgerInitCommand initCmd = new LedgerInitCommand(); | ||||
HashDigest ledgerHash = initCmd.startInit(id, privKey, base58Pwd, ledgerSetting, dbConnConfig, | HashDigest ledgerHash = initCmd.startInit(id, privKey, base58Pwd, ledgerSetting, dbConnConfig, | ||||
prompter, conf, db); | prompter, conf, db); | ||||
NodeWebContext.this.ledgerManager = initCmd.getLedgerManager(); | |||||
LedgerManager lm = initCmd.getLedgerManager(); | |||||
NodeWebContext.this.ledgerManager = lm; | |||||
quitLatch.countDown(); | quitLatch.countDown(); | ||||
return ledgerHash; | return ledgerHash; | ||||
} | } | ||||
@@ -460,6 +462,7 @@ public class LedgerInitializeWebTest { | |||||
return invoker.start(); | return invoker.start(); | ||||
} | } | ||||
public LedgerInitProposal preparePermision(PrivKey privKey, LedgerInitConfiguration initConfig) { | public LedgerInitProposal preparePermision(PrivKey privKey, LedgerInitConfiguration initConfig) { | ||||
return controller.prepareLocalPermission(id, privKey, initConfig); | return controller.prepareLocalPermission(id, privKey, initConfig); | ||||
} | } | ||||
@@ -517,7 +520,7 @@ public class LedgerInitializeWebTest { | |||||
// return ctx.getBean(LedgerManager.class); | // return ctx.getBean(LedgerManager.class); | ||||
} | } | ||||
public CompositeConnectionFactory getStorageDB() { | |||||
public DbConnectionFactory getStorageDB() { | |||||
return db; | return db; | ||||
} | } | ||||
} | } | ||||
@@ -14,58 +14,36 @@ | |||||
# limitations under the License. | # 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 ###### | ###### Consensus Participant0 ###### | ||||
############################################ | ############################################ | ||||
system.server.0.pubkey=3snPdw7i7PapsDoW185c3kfK6p8s6SwiJAdEUzgnfeuUox12nxgzXu | |||||
system.server.0.network.host=127.0.0.1 | system.server.0.network.host=127.0.0.1 | ||||
system.server.0.network.port=8910 | system.server.0.network.port=8910 | ||||
system.server.0.network.secure=false | system.server.0.network.secure=false | ||||
############################################ | ############################################ | ||||
###### #Consensus Participant1 ###### | ###### #Consensus Participant1 ###### | ||||
############################################ | ############################################ | ||||
system.server.1.pubkey=3snPdw7i7Ph1SYLQt9uqVEqiuvNXjxCdGvEdN6otJsg5rbr7Aze7kf | |||||
system.server.1.network.host=127.0.0.1 | system.server.1.network.host=127.0.0.1 | ||||
system.server.1.network.port=8920 | system.server.1.network.port=8920 | ||||
system.server.1.network.secure=false | system.server.1.network.secure=false | ||||
############################################ | ############################################ | ||||
###### #Consensus Participant2 ###### | ###### #Consensus Participant2 ###### | ||||
############################################ | ############################################ | ||||
system.server.2.pubkey=3snPdw7i7PezptA6dNBkotPjmKEbTkY8fmusLBnfj8Cf7eFwhWDwKr | |||||
system.server.2.network.host=127.0.0.1 | system.server.2.network.host=127.0.0.1 | ||||
system.server.2.network.port=8930 | system.server.2.network.port=8930 | ||||
system.server.2.network.secure=false | system.server.2.network.secure=false | ||||
############################################ | ############################################ | ||||
###### Consensus Participant3 ###### | ###### Consensus Participant3 ###### | ||||
############################################ | ############################################ | ||||
system.server.3.pubkey=3snPdw7i7PerZYfRzEB61SAN9tFK4yHm9wUSRtkLSSGXHkQRbB5PkS | |||||
system.server.3.network.host=127.0.0.1 | system.server.3.network.host=127.0.0.1 | ||||
system.server.3.network.port=8940 | system.server.3.network.port=8940 | ||||
system.server.3.network.secure=false | system.server.3.network.secure=false | ||||
############################################ | ############################################ | ||||
@@ -94,7 +72,7 @@ system.servers.num = 4 | |||||
#system.servers.f = 1 | #system.servers.f = 1 | ||||
#Timeout to asking for a client request | #Timeout to asking for a client request | ||||
system.totalordermulticast.timeout = 2000 | |||||
system.totalordermulticast.timeout = 5000 | |||||
#Maximum batch size (in number of messages) | #Maximum batch size (in number of messages) | ||||
@@ -174,5 +152,4 @@ system.ttp.id = 7002 | |||||
system.bft = true | system.bft = true | ||||
#Custom View Storage; | #Custom View Storage; | ||||
#view.storage.handler=bftsmart.reconfiguration.views.DefaultViewStorage | |||||
#view.storage.handler=bftsmart.reconfiguration.views.DefaultViewStorage |
@@ -2,7 +2,10 @@ | |||||
ledger.seed=932dfe23-fe23232f-283f32fa-dd32aa76-8322ca2f-56236cda-7136b322-cb323ffe | 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 | consensus.service-provider=com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider | ||||
@@ -103,6 +103,36 @@ public class IntegrationBase { | |||||
return keyPairResponse; | 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, | public static KeyPairResponse testSDK_RegisterDataAccount(AsymmetricKeypair adminKey, HashDigest ledgerHash, | ||||
BlockchainService blockchainService) { | BlockchainService blockchainService) { | ||||
// 注册数据账户,并验证最终写入; | // 注册数据账户,并验证最终写入; | ||||
@@ -47,16 +47,16 @@ public class IntegrationBaseTest { | |||||
Node node3 = context.getNode(3); | Node node3 = context.getNode(3); | ||||
NetworkAddress peerSrvAddr0 = new NetworkAddress("127.0.0.1", 13200); | 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); | 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); | 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); | 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<Object> peerStarting0 = peer0.start(); | AsyncCallback<Object> peerStarting0 = peer0.start(); | ||||
AsyncCallback<Object> peerStarting1 = peer1.start(); | AsyncCallback<Object> peerStarting1 = peer1.start(); | ||||
@@ -64,16 +64,16 @@ public class IntegrationTest2 { | |||||
Node node3 = context.getNode(3); | Node node3 = context.getNode(3); | ||||
NetworkAddress peerSrvAddr0 = new NetworkAddress("127.0.0.1", 13200); | 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); | 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); | 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); | 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<Object> peerStarting0 = peer0.start(); | AsyncCallback<Object> peerStarting0 = peer0.start(); | ||||
AsyncCallback<Object> peerStarting1 = peer1.start(); | AsyncCallback<Object> peerStarting1 = peer1.start(); | ||||
@@ -78,16 +78,16 @@ public class IntegrationTestDataAccount { | |||||
Node node3 = context.getNode(3); | Node node3 = context.getNode(3); | ||||
NetworkAddress peerSrvAddr0 = new NetworkAddress("127.0.0.1", 14200); | 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); | 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); | 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); | 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<Object> peerStarting0 = peer0.start(); | AsyncCallback<Object> peerStarting0 = peer0.start(); | ||||
AsyncCallback<Object> peerStarting1 = peer1.start(); | AsyncCallback<Object> peerStarting1 = peer1.start(); | ||||