| @@ -400,19 +400,20 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer | |||||
| int msgId = 0; | int msgId = 0; | ||||
| boolean isOK = true; | boolean isOK = true; | ||||
| TransactionState transactionState = TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK; | |||||
| 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 { | try { | ||||
| AsyncFuture<byte[]> asyncFuture = messageHandle.processOrdered(msgId++, txContent, realmName, batchId); | AsyncFuture<byte[]> asyncFuture = messageHandle.processOrdered(msgId++, txContent, realmName, batchId); | ||||
| asyncFutureLinkedList.add(asyncFuture); | asyncFutureLinkedList.add(asyncFuture); | ||||
| } catch (BlockRollbackException e) { | } catch (BlockRollbackException e) { | ||||
| LOGGER.error("Error occurred while processing ordered messages! --" + e.getMessage(), e); | LOGGER.error("Error occurred while processing ordered messages! --" + e.getMessage(), e); | ||||
| isOK = false; | isOK = false; | ||||
| // TODO: handle the BlockRollbackException in detail; | |||||
| if (e instanceof DataVersionConflictException) { | |||||
| transactionState = TransactionState.DATA_VERSION_CONFLICT; | |||||
| } | |||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| @@ -432,7 +433,7 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer | |||||
| } else { | } else { | ||||
| for (int i = 0; i < commands.length; i++) { | for (int i = 0; i < commands.length; i++) { | ||||
| responseLinkedList.add(createAppResponse(commands[i])); | |||||
| responseLinkedList.add(createAppResponse(commands[i],transactionState)); | |||||
| } | } | ||||
| Random random = new Random(); | 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); | 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.IGNORED_BY_BLOCK_FULL_ROLLBACK); | |||||
| resp.setExecutionState(transactionState); | |||||
| return BinaryProtocol.encode(resp, TransactionResponse.class); | return BinaryProtocol.encode(resp, TransactionResponse.class); | ||||
| } | } | ||||
| @@ -42,7 +42,7 @@ public class GatewayInterceptServiceHandler implements GatewayInterceptService { | |||||
| private void contractCheck(final ContractCodeDeployOperation contractOP) { | private void contractCheck(final ContractCodeDeployOperation contractOP) { | ||||
| // 校验chainCode | // 校验chainCode | ||||
| ContractJarUtils.verify(contractOP.getChainCode()); | |||||
| ContractJarUtils.verify(contractsPath, contractOP.getChainCode()); | |||||
| } | } | ||||
| private static String jarRootDir() { | private static String jarRootDir() { | ||||
| @@ -597,7 +597,7 @@ public class BlockBrowserController implements BlockchainExtendQueryService { | |||||
| public BlockchainIdentity[] getUsers(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | public BlockchainIdentity[] getUsers(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | ||||
| @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex, | @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex, | ||||
| @RequestParam(name = "count", required = false, defaultValue = "-1") int count) { | @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") | @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, | public BlockchainIdentity[] getDataAccounts(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | ||||
| @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex, | @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex, | ||||
| @RequestParam(name = "count", required = false, defaultValue = "-1") int count) { | @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") | @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, | public BlockchainIdentity[] getContractAccounts(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | ||||
| @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex, | @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex, | ||||
| @RequestParam(name = "count", required = false, defaultValue = "-1") int count) { | @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); | checkLedgerHash(ledgerHash); | ||||
| LedgerBlock block = ledger.getLatestBlock(); | LedgerBlock block = ledger.getLatestBlock(); | ||||
| UserAccountQuery userAccountSet = ledger.getUserAccountSet(block); | 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]); | return userAccountSet.getHeaders(pages[0], pages[1]); | ||||
| } | } | ||||
| @@ -414,7 +414,7 @@ public class LedgerQueryService implements BlockchainQueryService { | |||||
| checkLedgerHash(ledgerHash); | checkLedgerHash(ledgerHash); | ||||
| LedgerBlock block = ledger.getLatestBlock(); | LedgerBlock block = ledger.getLatestBlock(); | ||||
| DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); | 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]); | return dataAccountSet.getHeaders(pages[0], pages[1]); | ||||
| } | } | ||||
| @@ -423,7 +423,7 @@ public class LedgerQueryService implements BlockchainQueryService { | |||||
| checkLedgerHash(ledgerHash); | checkLedgerHash(ledgerHash); | ||||
| LedgerBlock block = ledger.getLatestBlock(); | LedgerBlock block = ledger.getLatestBlock(); | ||||
| ContractAccountQuery contractAccountSet = ledger.getContractAccountSet(block); | 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]); | return contractAccountSet.getHeaders(pages[0], pages[1]); | ||||
| } | } | ||||
| @@ -5,29 +5,11 @@ import java.util.Collection; | |||||
| import java.util.Iterator; | import java.util.Iterator; | ||||
| import java.util.List; | import java.util.List; | ||||
| import com.jd.blockchain.ledger.*; | |||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||
| import com.jd.blockchain.crypto.HashDigest; | 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.ledger.core.TransactionRequestExtension.Credential; | ||||
| import com.jd.blockchain.service.TransactionBatchProcess; | import com.jd.blockchain.service.TransactionBatchProcess; | ||||
| import com.jd.blockchain.service.TransactionBatchResult; | import com.jd.blockchain.service.TransactionBatchResult; | ||||
| @@ -63,7 +45,7 @@ public class TransactionBatchProcessor implements TransactionBatchProcess { | |||||
| /** | /** | ||||
| * @param newBlockEditor 新区块的数据编辑器; | * @param newBlockEditor 新区块的数据编辑器; | ||||
| * @param ledgerQueryer 账本查询器,只包含新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集; | |||||
| * @param newBlockEditor 账本查询器,只包含新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集; | |||||
| * @param opHandles 操作处理对象注册表; | * @param opHandles 操作处理对象注册表; | ||||
| */ | */ | ||||
| public TransactionBatchProcessor(LedgerSecurityManager securityManager, LedgerEditor newBlockEditor, | public TransactionBatchProcessor(LedgerSecurityManager securityManager, LedgerEditor newBlockEditor, | ||||
| @@ -153,6 +135,7 @@ public class TransactionBatchProcessor implements TransactionBatchProcess { | |||||
| } catch (BlockRollbackException e) { | } catch (BlockRollbackException e) { | ||||
| // 发生区块级别的处理异常,向上重新抛出异常进行处理,整个区块可能被丢弃; | // 发生区块级别的处理异常,向上重新抛出异常进行处理,整个区块可能被丢弃; | ||||
| resp = discard(request, e.getState()); | |||||
| LOGGER.error(String.format( | LOGGER.error(String.format( | ||||
| "Ignore transaction caused by BlockRollbackException! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s", | "Ignore transaction caused by BlockRollbackException! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s", | ||||
| newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(), | newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(), | ||||
| @@ -287,8 +270,12 @@ public class TransactionBatchProcessor implements TransactionBatchProcess { | |||||
| newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(), | newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(), | ||||
| e.getMessage()), e); | e.getMessage()), e); | ||||
| } catch (BlockRollbackException e) { | } catch (BlockRollbackException e) { | ||||
| // 回滚整个区块; | |||||
| // rollback all the block; | |||||
| // 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", | ||||
| @@ -498,7 +498,7 @@ public class LedgerQueryController implements BlockchainQueryService { | |||||
| LedgerQuery ledger = ledgerService.getLedger(ledgerHash); | LedgerQuery ledger = ledgerService.getLedger(ledgerHash); | ||||
| LedgerBlock block = ledger.getLatestBlock(); | LedgerBlock block = ledger.getLatestBlock(); | ||||
| UserAccountQuery userAccountSet = ledger.getUserAccountSet(block); | 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]); | return userAccountSet.getHeaders(pages[0], pages[1]); | ||||
| } | } | ||||
| @@ -518,7 +518,7 @@ public class LedgerQueryController implements BlockchainQueryService { | |||||
| LedgerQuery ledger = ledgerService.getLedger(ledgerHash); | LedgerQuery ledger = ledgerService.getLedger(ledgerHash); | ||||
| LedgerBlock block = ledger.getLatestBlock(); | LedgerBlock block = ledger.getLatestBlock(); | ||||
| DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); | 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]); | return dataAccountSet.getHeaders(pages[0], pages[1]); | ||||
| } | } | ||||
| @@ -530,7 +530,7 @@ public class LedgerQueryController implements BlockchainQueryService { | |||||
| LedgerQuery ledger = ledgerService.getLedger(ledgerHash); | LedgerQuery ledger = ledgerService.getLedger(ledgerHash); | ||||
| LedgerBlock block = ledger.getLatestBlock(); | LedgerBlock block = ledger.getLatestBlock(); | ||||
| ContractAccountQuery contractAccountSet = ledger.getContractAccountSet(block); | 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]); | return contractAccountSet.getHeaders(pages[0], pages[1]); | ||||
| } | } | ||||
| @@ -35,7 +35,7 @@ | |||||
| </modules> | </modules> | ||||
| <properties> | <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> | <data-explorer.version>1.1.0.RELEASE</data-explorer.version> | ||||
| <manager-explorer.version>1.1.0.RELEASE</manager-explorer.version> | <manager-explorer.version>1.1.0.RELEASE</manager-explorer.version> | ||||
| <commons-io.version>2.4</commons-io.version> | <commons-io.version>2.4</commons-io.version> | ||||
| @@ -240,7 +240,7 @@ public abstract class RuntimeContext { | |||||
| private static void initBlacks() { | private static void initBlacks() { | ||||
| try { | try { | ||||
| InputStream inputStream = ContractURLClassLoader.class.getResourceAsStream(File.separator + BLACK_CONFIG); | |||||
| InputStream inputStream = ContractURLClassLoader.class.getResourceAsStream("/"+ BLACK_CONFIG); | |||||
| String text = FileUtils.readText(inputStream); | String text = FileUtils.readText(inputStream); | ||||
| String[] textArray = text.split("\n"); | String[] textArray = text.split("\n"); | ||||
| for (String setting : textArray) { | for (String setting : textArray) { | ||||
| @@ -47,4 +47,21 @@ public class QueryUtil { | |||||
| rtn[1] = count; | rtn[1] = count; | ||||
| return rtn; | 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; | |||||
| } | |||||
| } | } | ||||