Search in sources :

Example 1 with AsyncFuture

use of utils.concurrent.AsyncFuture in project jdchain-core by blockchain-jd-com.

the class BlockCommitService method commitBlock.

public boolean commitBlock(Block block, BlockClosure done) throws BlockCommittedException {
    boolean result = true;
    long latestBlockHeight = ledgerRepository.retrieveLatestBlockHeight();
    if (latestBlockHeight >= block.getHeight()) {
        throw new BlockCommittedException(block.getHeight());
    }
    if (latestBlockHeight + 1 != block.getHeight()) {
        notifyCatchUp(block.getHeight());
        LOGGER.error("commit block ignore. expect height:{}, latest block: {}", block.getHeight(), latestBlockHeight);
        return false;
    }
    RaftConsensusMessageContext context = RaftConsensusMessageContext.createContext(realmName);
    context.setTimestamp(block.getProposalTimestamp());
    String batch = messageHandle.beginBatch(context);
    context.setBatchId(batch);
    LoggerUtils.debugIfEnabled(LOGGER, "commit block start, batchId: {}", batch);
    Status status = Status.OK();
    try {
        int msgId = 0;
        for (byte[] tx : block.getTxs()) {
            AsyncFuture<byte[]> asyncFuture = messageHandle.processOrdered(msgId++, tx, context);
            Optional.ofNullable(done).ifPresent(d -> d.addFuture(asyncFuture));
        }
        messageHandle.completeBatch(context);
        // todo ?
        messageHandle.commitBatch(context);
        LedgerBlock repositoryLatestBlock = ledgerRepository.getLatestBlock();
        assert repositoryLatestBlock.getHeight() == block.getHeight();
        block.setPreBlockHash(repositoryLatestBlock.getPreviousHash());
        block.setCurrentBlockHash(repositoryLatestBlock.getHash());
        blockCommitCallbackList.forEach(c -> c.commitCallBack(block, true));
    } catch (Exception e) {
        LOGGER.error("commitBlock error", e);
        result = false;
        messageHandle.rollbackBatch(TransactionState.CONSENSUS_ERROR.CODE, context);
        status = new Status(TransactionState.CONSENSUS_ERROR.CODE, e.getMessage());
        blockCommitCallbackList.forEach(c -> c.commitCallBack(block, false));
    }
    LoggerUtils.debugIfEnabled(LOGGER, "commit block end, batchId: {}, blockHeight: {}, status: {}", batch, block.getHeight(), status);
    if (done != null) {
        done.run(status);
    }
    return result;
}
Also used : Status(com.alipay.sofa.jraft.Status) Longs(com.google.common.primitives.Longs) Logger(org.slf4j.Logger) MessageHandle(com.jd.blockchain.consensus.service.MessageHandle) TransactionState(com.jd.blockchain.ledger.TransactionState) BlockCommitCallback(com.jd.blockchain.consensus.raft.consensus.BlockCommitCallback) MessageBus(com.jd.blockchain.consensus.raft.msgbus.MessageBus) BlockCommittedException(com.jd.blockchain.consensus.raft.consensus.BlockCommittedException) LoggerFactory(org.slf4j.LoggerFactory) LedgerBlock(com.jd.blockchain.ledger.LedgerBlock) LedgerRepository(com.jd.blockchain.ledger.core.LedgerRepository) Status(com.alipay.sofa.jraft.Status) LoggerUtils(com.jd.blockchain.consensus.raft.util.LoggerUtils) ArrayList(java.util.ArrayList) List(java.util.List) AsyncFuture(utils.concurrent.AsyncFuture) BLOCK_CATCH_UP_TOPIC(com.jd.blockchain.consensus.raft.msgbus.MessageBus.BLOCK_CATCH_UP_TOPIC) Block(com.jd.blockchain.consensus.raft.consensus.Block) Optional(java.util.Optional) BlockCommitter(com.jd.blockchain.consensus.raft.consensus.BlockCommitter) LedgerBlock(com.jd.blockchain.ledger.LedgerBlock) BlockCommittedException(com.jd.blockchain.consensus.raft.consensus.BlockCommittedException) BlockCommittedException(com.jd.blockchain.consensus.raft.consensus.BlockCommittedException)

Example 2 with AsyncFuture

use of utils.concurrent.AsyncFuture in project jdchain-core by blockchain-jd-com.

the class BftsmartNodeServer method preComputeAppHash.

/**
 * From consensus outcomes, do nothing now The operation of executing the batch
 * was moved to the consensus stage 2 and 3, in order to guaranteed ledger
 * consistency
 */
// @Override
// public byte[][] appExecuteBatch(byte[][] commands, MessageContext[] msgCtxs, boolean fromConsensus) {
// if (replyList == null || replyList.size() == 0) {
// throw new IllegalArgumentException();
// }
// // todo 此部分需要重新改造
// /**
// * 默认BFTSmart接口提供的commands是一个或多个共识结果的顺序集合
// * 根据共识的规定,目前的做法是将其根据msgCtxs的内容进行分组,每组都作为一个结块标识来处理
// * 从msgCtxs可以获取对应commands的分组情况
// */
// int manageConsensusId = msgCtxs[0].getConsensusId();
// List<byte[]> manageConsensusCmds = new ArrayList<>();
// List<ReplyContextMessage> manageReplyMsgs = new ArrayList<>();
// 
// int index = 0;
// for (MessageContext msgCtx : msgCtxs) {
// if (msgCtx.getConsensusId() == manageConsensusId) {
// manageConsensusCmds.add(commands[index]);
// manageReplyMsgs.add(replyList.get(index));
// } else {
// // 达到结块标准,需要进行结块并应答
// blockAndReply(manageConsensusCmds, manageReplyMsgs);
// // 重置链表和共识ID
// manageConsensusCmds = new ArrayList<>();
// manageReplyMsgs = new ArrayList<>();
// manageConsensusId = msgCtx.getConsensusId();
// manageConsensusCmds.add(commands[index]);
// manageReplyMsgs.add(replyList.get(index));
// }
// index++;
// }
// // 结束时,肯定有最后一个结块请求未处理
// if (!manageConsensusCmds.isEmpty()) {
// blockAndReply(manageConsensusCmds, manageReplyMsgs);
// }
// return null;
// }
/**
 * Block and reply are moved to consensus completion stage
 */
// private void blockAndReply(List<byte[]> manageConsensusCmds, List<ReplyContextMessage> replyList) {
// consensusBatchId = messageHandle.beginBatch(realmName);
// List<AsyncFuture<byte[]>> asyncFutureLinkedList = new ArrayList<>(manageConsensusCmds.size());
// try {
// int msgId = 0;
// for (byte[] txContent : manageConsensusCmds) {
// AsyncFuture<byte[]> asyncFuture = messageHandle.processOrdered(msgId++, txContent, realmName, consensusBatchId);
// asyncFutureLinkedList.add(asyncFuture);
// }
// messageHandle.completeBatch(realmName, consensusBatchId);
// messageHandle.commitBatch(realmName, consensusBatchId);
// } catch (Exception e) {
// // todo 需要处理应答码 404
// LOGGER.error("Error occurred while processing ordered messages! --" + e.getMessage(), e);
// messageHandle.rollbackBatch(realmName, consensusBatchId, TransactionState.CONSENSUS_ERROR.CODE);
// }
// 
// // 通知线程单独处理应答
// notifyReplyExecutors.execute(() -> {
// // 应答对应的结果
// int replyIndex = 0;
// for(ReplyContextMessage msg : replyList) {
// msg.setReply(asyncFutureLinkedList.get(replyIndex).get());
// TOMMessage request = msg.getTomMessage();
// ReplyContext replyContext = msg.getReplyContext();
// request.reply = new TOMMessage(replyContext.getId(), request.getSession(), request.getSequence(),
// request.getOperationId(), msg.getReply(), replyContext.getCurrentViewId(),
// request.getReqType());
// 
// if (replyContext.getNumRepliers() > 0) {
// bftsmart.tom.util.Logger.println("(ServiceReplica.receiveMessages) sending reply to "
// + request.getSender() + " with sequence number " + request.getSequence()
// + " and operation ID " + request.getOperationId() + " via ReplyManager");
// replyContext.getRepMan().send(request);
// } else {
// bftsmart.tom.util.Logger.println("(ServiceReplica.receiveMessages) sending reply to "
// + request.getSender() + " with sequence number " + request.getSequence()
// + " and operation ID " + request.getOperationId());
// replyContext.getReplier().manageReply(request, msg.getMessageContext());
// }
// replyIndex++;
// }
// });
// }
/**
 * Used by consensus write phase, pre compute new block hash
 *
 * @param cid      当前正在进行的共识ID;
 * @param commands 请求列表
 */
@Override
public BatchAppResultImpl preComputeAppHash(int cid, byte[][] commands, long timestamp) {
    List<AsyncFuture<byte[]>> asyncFutureLinkedList = new ArrayList<>(commands.length);
    List<byte[]> responseLinkedList = new ArrayList<>();
    StateSnapshot newStateSnapshot, preStateSnapshot, genisStateSnapshot;
    BatchAppResultImpl result;
    String batchId = "";
    int msgId = 0;
    byte[] cidBytes = BytesUtils.toBytes(cid);
    batchHandleLock.lock();
    try {
        if (commands.length == 0) {
            // 没有要做预计算的消息,直接组装结果返回
            result = BatchAppResultImpl.createFailure(responseLinkedList, cidBytes, batchId, cidBytes);
        } else {
            BftsmartConsensusMessageContext context = BftsmartConsensusMessageContext.createInstance(realmName, timestamp);
            batchId = messageHandle.beginBatch(context);
            context.setBatchId(batchId);
            contexts.put(batchId, context);
            stateHolder.batchingID = batchId;
            // 获取前置区块快照状态
            preStateSnapshot = messageHandle.getLatestStateSnapshot(realmName);
            if (preStateSnapshot instanceof BlockStateSnapshot) {
                BlockStateSnapshot preBlockStateSnapshot = (BlockStateSnapshot) preStateSnapshot;
                long preBlockTimestamp = preBlockStateSnapshot.getTimestamp();
                if (timestamp < preBlockTimestamp && (preBlockTimestamp - timestamp) > timeTolerance) {
                    // 打印错误信息
                    LOGGER.warn("The time[{}] of the last block is mismatch with the current[{}] for time tolerance[{}] !!!", preBlockTimestamp, timestamp, timeTolerance);
                    // 设置返回的应答信息
                    for (byte[] command : commands) {
                        // 状态设置为共识错误
                        responseLinkedList.add(createAppResponse(command, TransactionState.CONSENSUS_TIMESTAMP_ERROR));
                    }
                    // 将该状态设置为未执行
                    stateHolder.setComputeStatus(PreComputeStatus.UN_EXECUTED);
                    // 回滚该操作
                    messageHandle.rollbackBatch(TransactionState.CONSENSUS_TIMESTAMP_ERROR.CODE, context);
                    // 返回成功,但需要设置当前的状态
                    return BatchAppResultImpl.createSuccess(responseLinkedList, cidBytes, batchId, cidBytes);
                } else {
                    LOGGER.debug("Last block's timestamp = {}, current timestamp = {}, time tolerance = {} !", preBlockTimestamp, timestamp, timeTolerance);
                }
            }
            // 创世区块的状态快照
            genisStateSnapshot = messageHandle.getGenesisStateSnapshot(realmName);
            for (byte[] txContent : commands) {
                AsyncFuture<byte[]> asyncFuture = messageHandle.processOrdered(msgId++, txContent, context);
                asyncFutureLinkedList.add(asyncFuture);
            }
            newStateSnapshot = messageHandle.completeBatch(context);
            for (AsyncFuture<byte[]> asyncFuture : asyncFutureLinkedList) {
                responseLinkedList.add(asyncFuture.get());
            }
            result = BatchAppResultImpl.createSuccess(responseLinkedList, newStateSnapshot.getSnapshot(), batchId, genisStateSnapshot.getSnapshot());
        }
    } catch (BlockRollbackException e) {
        LOGGER.error("Error occurred while pre compute app! --" + e.getMessage(), e);
        for (byte[] command : commands) {
            responseLinkedList.add(createAppResponse(command, e.getState()));
        }
        result = BatchAppResultImpl.createFailure(responseLinkedList, cidBytes, batchId, cidBytes);
    } catch (Exception e) {
        LOGGER.error("Error occurred while pre compute app! --" + e.getMessage(), e);
        for (byte[] command : commands) {
            responseLinkedList.add(createAppResponse(command, TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK));
        }
        result = BatchAppResultImpl.createFailure(responseLinkedList, cidBytes, batchId, cidBytes);
    } finally {
        batchHandleLock.unlock();
    }
    return result;
}
Also used : ArrayList(java.util.ArrayList) BlockStateSnapshot(com.jd.blockchain.consensus.BlockStateSnapshot) StateSnapshot(com.jd.blockchain.consensus.service.StateSnapshot) BatchAppResultImpl(bftsmart.consensus.app.BatchAppResultImpl) BlockRollbackException(com.jd.blockchain.ledger.BlockRollbackException) BlockRollbackException(com.jd.blockchain.ledger.BlockRollbackException) CompletableAsyncFuture(utils.concurrent.CompletableAsyncFuture) AsyncFuture(utils.concurrent.AsyncFuture) BlockStateSnapshot(com.jd.blockchain.consensus.BlockStateSnapshot)

Aggregations

ArrayList (java.util.ArrayList)2 AsyncFuture (utils.concurrent.AsyncFuture)2 BatchAppResultImpl (bftsmart.consensus.app.BatchAppResultImpl)1 Status (com.alipay.sofa.jraft.Status)1 Longs (com.google.common.primitives.Longs)1 BlockStateSnapshot (com.jd.blockchain.consensus.BlockStateSnapshot)1 Block (com.jd.blockchain.consensus.raft.consensus.Block)1 BlockCommitCallback (com.jd.blockchain.consensus.raft.consensus.BlockCommitCallback)1 BlockCommittedException (com.jd.blockchain.consensus.raft.consensus.BlockCommittedException)1 BlockCommitter (com.jd.blockchain.consensus.raft.consensus.BlockCommitter)1 MessageBus (com.jd.blockchain.consensus.raft.msgbus.MessageBus)1 BLOCK_CATCH_UP_TOPIC (com.jd.blockchain.consensus.raft.msgbus.MessageBus.BLOCK_CATCH_UP_TOPIC)1 LoggerUtils (com.jd.blockchain.consensus.raft.util.LoggerUtils)1 MessageHandle (com.jd.blockchain.consensus.service.MessageHandle)1 StateSnapshot (com.jd.blockchain.consensus.service.StateSnapshot)1 BlockRollbackException (com.jd.blockchain.ledger.BlockRollbackException)1 LedgerBlock (com.jd.blockchain.ledger.LedgerBlock)1 TransactionState (com.jd.blockchain.ledger.TransactionState)1 LedgerRepository (com.jd.blockchain.ledger.core.LedgerRepository)1 List (java.util.List)1