| @@ -400,19 +400,20 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer | |||
| int msgId = 0; | |||
| boolean isOK = true; | |||
| TransactionState transactionState = TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK; | |||
| for (int i = 0; i < commands.length; 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; | |||
| } | |||
| } | |||
| @@ -432,7 +433,7 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer | |||
| } else { | |||
| for (int i = 0; i < commands.length; i++) { | |||
| responseLinkedList.add(createAppResponse(commands[i])); | |||
| responseLinkedList.add(createAppResponse(commands[i],transactionState)); | |||
| } | |||
| Random random = new Random(); | |||
| @@ -451,11 +452,12 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer | |||
| } | |||
| } | |||
| public byte[] createAppResponse(byte[] command) { | |||
| public byte[] createAppResponse(byte[] command, TransactionState transactionState) { | |||
| TransactionRequest txRequest = BinaryProtocol.decode(command); | |||
| TxResponseMessage resp = new TxResponseMessage(txRequest.getTransactionContent().getHash()); | |||
| resp.setExecutionState(TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK); | |||
| // resp.setExecutionState(TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK); | |||
| resp.setExecutionState(transactionState); | |||
| return BinaryProtocol.encode(resp, TransactionResponse.class); | |||
| } | |||
| @@ -42,7 +42,7 @@ public class GatewayInterceptServiceHandler implements GatewayInterceptService { | |||
| private void contractCheck(final ContractCodeDeployOperation contractOP) { | |||
| // 校验chainCode | |||
| ContractJarUtils.verify(contractOP.getChainCode()); | |||
| ContractJarUtils.verify(contractsPath, contractOP.getChainCode()); | |||
| } | |||
| private static String jarRootDir() { | |||
| @@ -597,7 +597,7 @@ public class BlockBrowserController implements BlockchainExtendQueryService { | |||
| public BlockchainIdentity[] getUsers(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | |||
| @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex, | |||
| @RequestParam(name = "count", required = false, defaultValue = "-1") int count) { | |||
| return peerService.getQueryService().getUsers(ledgerHash, fromIndex, count); | |||
| return revertAccountHeader(peerService.getQueryService().getUsers(ledgerHash, fromIndex, count)); | |||
| } | |||
| @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/accounts") | |||
| @@ -605,7 +605,7 @@ public class BlockBrowserController implements BlockchainExtendQueryService { | |||
| public BlockchainIdentity[] getDataAccounts(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | |||
| @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex, | |||
| @RequestParam(name = "count", required = false, defaultValue = "-1") int count) { | |||
| return peerService.getQueryService().getDataAccounts(ledgerHash, fromIndex, count); | |||
| return revertAccountHeader(peerService.getQueryService().getDataAccounts(ledgerHash, fromIndex, count)); | |||
| } | |||
| @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/contracts") | |||
| @@ -613,6 +613,20 @@ public class BlockBrowserController implements BlockchainExtendQueryService { | |||
| public BlockchainIdentity[] getContractAccounts(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | |||
| @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex, | |||
| @RequestParam(name = "count", required = false, defaultValue = "-1") int count) { | |||
| return peerService.getQueryService().getContractAccounts(ledgerHash, fromIndex, count); | |||
| return revertAccountHeader(peerService.getQueryService().getContractAccounts(ledgerHash, fromIndex, count)); | |||
| } | |||
| /** | |||
| * reverse the AccountHeader[] content; the latest record show first; | |||
| * @return | |||
| */ | |||
| private AccountHeader[] revertAccountHeader(AccountHeader[] accountHeaders){ | |||
| AccountHeader[] accounts = new AccountHeader[accountHeaders.length]; | |||
| if(accountHeaders!=null && accountHeaders.length>0){ | |||
| for (int i = 0; i < accountHeaders.length; i++) { | |||
| accounts[accountHeaders.length-1-i] = accountHeaders[i]; | |||
| } | |||
| } | |||
| return accounts; | |||
| } | |||
| } | |||
| @@ -405,7 +405,7 @@ public class LedgerQueryService implements BlockchainQueryService { | |||
| checkLedgerHash(ledgerHash); | |||
| LedgerBlock block = ledger.getLatestBlock(); | |||
| UserAccountQuery userAccountSet = ledger.getUserAccountSet(block); | |||
| int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) userAccountSet.getTotal()); | |||
| int pages[] = QueryUtil.calFromIndexAndCountDescend(fromIndex, count, (int) userAccountSet.getTotal()); | |||
| return userAccountSet.getHeaders(pages[0], pages[1]); | |||
| } | |||
| @@ -414,7 +414,7 @@ public class LedgerQueryService implements BlockchainQueryService { | |||
| checkLedgerHash(ledgerHash); | |||
| LedgerBlock block = ledger.getLatestBlock(); | |||
| DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); | |||
| int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) dataAccountSet.getTotal()); | |||
| int pages[] = QueryUtil.calFromIndexAndCountDescend(fromIndex, count, (int) dataAccountSet.getTotal()); | |||
| return dataAccountSet.getHeaders(pages[0], pages[1]); | |||
| } | |||
| @@ -423,7 +423,7 @@ public class LedgerQueryService implements BlockchainQueryService { | |||
| checkLedgerHash(ledgerHash); | |||
| LedgerBlock block = ledger.getLatestBlock(); | |||
| ContractAccountQuery contractAccountSet = ledger.getContractAccountSet(block); | |||
| int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) contractAccountSet.getTotal()); | |||
| int pages[] = QueryUtil.calFromIndexAndCountDescend(fromIndex, count, (int) contractAccountSet.getTotal()); | |||
| return contractAccountSet.getHeaders(pages[0], pages[1]); | |||
| } | |||
| @@ -5,29 +5,11 @@ import java.util.Collection; | |||
| import java.util.Iterator; | |||
| import java.util.List; | |||
| import com.jd.blockchain.ledger.*; | |||
| import org.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| import com.jd.blockchain.crypto.HashDigest; | |||
| import com.jd.blockchain.ledger.BlockRollbackException; | |||
| import com.jd.blockchain.ledger.BytesValue; | |||
| import com.jd.blockchain.ledger.ContractDoesNotExistException; | |||
| import com.jd.blockchain.ledger.DataAccountDoesNotExistException; | |||
| import com.jd.blockchain.ledger.IllegalTransactionException; | |||
| import com.jd.blockchain.ledger.LedgerBlock; | |||
| import com.jd.blockchain.ledger.LedgerException; | |||
| import com.jd.blockchain.ledger.LedgerPermission; | |||
| import com.jd.blockchain.ledger.LedgerSecurityException; | |||
| import com.jd.blockchain.ledger.Operation; | |||
| import com.jd.blockchain.ledger.OperationResult; | |||
| import com.jd.blockchain.ledger.OperationResultData; | |||
| import com.jd.blockchain.ledger.ParticipantDoesNotExistException; | |||
| import com.jd.blockchain.ledger.TransactionContent; | |||
| import com.jd.blockchain.ledger.TransactionRequest; | |||
| import com.jd.blockchain.ledger.TransactionResponse; | |||
| import com.jd.blockchain.ledger.TransactionRollbackException; | |||
| import com.jd.blockchain.ledger.TransactionState; | |||
| import com.jd.blockchain.ledger.UserDoesNotExistException; | |||
| import com.jd.blockchain.ledger.core.TransactionRequestExtension.Credential; | |||
| import com.jd.blockchain.service.TransactionBatchProcess; | |||
| import com.jd.blockchain.service.TransactionBatchResult; | |||
| @@ -63,7 +45,7 @@ public class TransactionBatchProcessor implements TransactionBatchProcess { | |||
| /** | |||
| * @param newBlockEditor 新区块的数据编辑器; | |||
| * @param ledgerQueryer 账本查询器,只包含新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集; | |||
| * @param newBlockEditor 账本查询器,只包含新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集; | |||
| * @param opHandles 操作处理对象注册表; | |||
| */ | |||
| public TransactionBatchProcessor(LedgerSecurityManager securityManager, LedgerEditor newBlockEditor, | |||
| @@ -153,6 +135,7 @@ public class TransactionBatchProcessor implements TransactionBatchProcess { | |||
| } catch (BlockRollbackException e) { | |||
| // 发生区块级别的处理异常,向上重新抛出异常进行处理,整个区块可能被丢弃; | |||
| resp = discard(request, e.getState()); | |||
| LOGGER.error(String.format( | |||
| "Ignore transaction caused by BlockRollbackException! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s", | |||
| newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(), | |||
| @@ -287,8 +270,12 @@ public class TransactionBatchProcessor implements TransactionBatchProcess { | |||
| newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(), | |||
| e.getMessage()), e); | |||
| } catch (BlockRollbackException e) { | |||
| // 回滚整个区块; | |||
| // rollback all the block; | |||
| // TODO: handle the BlockRollbackException in detail; | |||
| result = TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK; | |||
| if (e instanceof DataVersionConflictException) { | |||
| result = TransactionState.DATA_VERSION_CONFLICT; | |||
| } | |||
| txCtx.rollback(); | |||
| LOGGER.error( | |||
| String.format("Transaction was rolled back! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s", | |||
| @@ -498,7 +498,7 @@ public class LedgerQueryController implements BlockchainQueryService { | |||
| LedgerQuery ledger = ledgerService.getLedger(ledgerHash); | |||
| LedgerBlock block = ledger.getLatestBlock(); | |||
| UserAccountQuery userAccountSet = ledger.getUserAccountSet(block); | |||
| int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) userAccountSet.getTotal()); | |||
| int pages[] = QueryUtil.calFromIndexAndCountDescend(fromIndex, count, (int) userAccountSet.getTotal()); | |||
| return userAccountSet.getHeaders(pages[0], pages[1]); | |||
| } | |||
| @@ -518,7 +518,7 @@ public class LedgerQueryController implements BlockchainQueryService { | |||
| LedgerQuery ledger = ledgerService.getLedger(ledgerHash); | |||
| LedgerBlock block = ledger.getLatestBlock(); | |||
| DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); | |||
| int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) dataAccountSet.getTotal()); | |||
| int pages[] = QueryUtil.calFromIndexAndCountDescend(fromIndex, count, (int) dataAccountSet.getTotal()); | |||
| return dataAccountSet.getHeaders(pages[0], pages[1]); | |||
| } | |||
| @@ -530,7 +530,7 @@ public class LedgerQueryController implements BlockchainQueryService { | |||
| LedgerQuery ledger = ledgerService.getLedger(ledgerHash); | |||
| LedgerBlock block = ledger.getLatestBlock(); | |||
| ContractAccountQuery contractAccountSet = ledger.getContractAccountSet(block); | |||
| int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) contractAccountSet.getTotal()); | |||
| int pages[] = QueryUtil.calFromIndexAndCountDescend(fromIndex, count, (int) contractAccountSet.getTotal()); | |||
| return contractAccountSet.getHeaders(pages[0], pages[1]); | |||
| } | |||
| @@ -35,7 +35,7 @@ | |||
| </modules> | |||
| <properties> | |||
| <bft-smart.version>0.2.0.RELEASE</bft-smart.version> | |||
| <bft-smart.version>0.3.0-SNAPSHOT</bft-smart.version> | |||
| <data-explorer.version>1.1.0.RELEASE</data-explorer.version> | |||
| <manager-explorer.version>1.1.0.RELEASE</manager-explorer.version> | |||
| <commons-io.version>2.4</commons-io.version> | |||
| @@ -240,7 +240,7 @@ public abstract class RuntimeContext { | |||
| private static void initBlacks() { | |||
| try { | |||
| InputStream inputStream = ContractURLClassLoader.class.getResourceAsStream(File.separator + BLACK_CONFIG); | |||
| InputStream inputStream = ContractURLClassLoader.class.getResourceAsStream("/"+ BLACK_CONFIG); | |||
| String text = FileUtils.readText(inputStream); | |||
| String[] textArray = text.split("\n"); | |||
| for (String setting : textArray) { | |||
| @@ -47,4 +47,21 @@ public class QueryUtil { | |||
| rtn[1] = count; | |||
| return rtn; | |||
| } | |||
| /** | |||
| * cal the data by descend; | |||
| * @param fromIndex | |||
| * @param count | |||
| * @param maxNum | |||
| * @return | |||
| */ | |||
| public static int[] calFromIndexAndCountDescend(int fromIndex, int count, int maxNum){ | |||
| int rtn[] = new int[2]; | |||
| int results[] = calFromIndexAndCount(fromIndex,count,maxNum); | |||
| //now use descend; first show the latest record; | |||
| rtn[0] = maxNum - results[0] - results[1]; | |||
| rtn[1] = results[1]; | |||
| return rtn; | |||
| } | |||
| } | |||