@@ -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; | |||||
} | |||||
} | } |