Search in sources :

Example 1 with ChainContainer

use of io.nuls.consensus.poc.container.ChainContainer in project nuls by nuls-io.

the class ForkChainProcess method findWantToChangeChain.

/**
 * 查询当前所有分叉链里,是否存在可切换为主链的
 * 可切换主链规则:
 *    1.高度和主链相同,出块人为同一个人,说明有出块节点在同一时间出了两个块,我们统一选择hash大的那个作为主链
 *    2.当前有分叉链比主网高度高出3个块
 * @param masterBestHeader
 * @return
 */
private ChainContainer findWantToChangeChain(BlockHeader masterBestHeader) {
    ChainContainer changeContainer = null;
    long newestBlockHeight = chainManager.getBestBlockHeight() + PocConsensusConstant.CHANGE_CHAIN_BLOCK_DIFF_COUNT;
    Iterator<ChainContainer> iterator = chainManager.getChains().iterator();
    BlockHeader forkChainBestHeader = null;
    byte[] rightHash = null;
    while (iterator.hasNext()) {
        ChainContainer forkChain = iterator.next();
        // 删除格式错误的分叉链
        if (forkChain.getChain() == null || forkChain.getChain().getStartBlockHeader() == null || forkChain.getChain().getEndBlockHeader() == null) {
            iterator.remove();
            continue;
        }
        forkChainBestHeader = forkChain.getChain().getEndBlockHeader();
        // 同一高度有人出了两个块,判断哪条链的块hash值更小,如果分叉链的块hash值更小,则切换到分叉链
        if (masterBestHeader.getHeight() == forkChainBestHeader.getHeight() && masterBestHeader.getPackingAddressStr().equals(forkChainBestHeader.getPackingAddressStr())) {
            byte[] smallHash = compareHashAndGetSmall(masterBestHeader.getHash().getDigestBytes(), forkChainBestHeader.getHash().getDigestBytes());
            if (!ArraysTool.arrayEquals(smallHash, masterBestHeader.getHash().getDigestBytes())) {
                rightHash = smallHash;
                changeContainer = forkChain;
                newestBlockHeight = masterBestHeader.getHeight();
                Log.info("-+-+-+-+-+-+-+-+- Change chain with the same height but different hash block -+-+-+-+-+-+-+-+-");
                break;
            }
        }
        if (forkChainBestHeader.getHeight() > newestBlockHeight || (forkChainBestHeader.getHeight() == newestBlockHeight && changeContainer != null && forkChainBestHeader.getTime() < changeContainer.getChain().getEndBlockHeader().getTime())) {
            changeContainer = forkChain;
            newestBlockHeight = forkChainBestHeader.getHeight();
            rightHash = forkChainBestHeader.getHash().getDigestBytes();
        }
    }
    if (changeContainer != null) {
        Log.info("-+-+-+-+-+-+-+-+- height: " + newestBlockHeight + ", Right hash:" + Hex.encode(rightHash));
        /**
         ********************************************************************************************************
         */
        try {
            Log.info("");
            Log.info("****************************************************");
            Log.info("准备开始切换链,获取当前bestblock, height:{},- hash{}", chainManager.getBestBlock().getHeader().getHeight(), chainManager.getBestBlock().getHeader().getHash());
            Log.info("****************************************************");
            Log.info("");
        } catch (Exception e) {
            e.printStackTrace();
        }
    /**
     ********************************************************************************************************
     */
    }
    return changeContainer;
}
Also used : ChainContainer(io.nuls.consensus.poc.container.ChainContainer) IOException(java.io.IOException) NulsException(io.nuls.kernel.exception.NulsException)

Example 2 with ChainContainer

use of io.nuls.consensus.poc.container.ChainContainer in project nuls by nuls-io.

the class ForkChainProcess method clearExpiredChain.

protected void clearExpiredChain() {
    if (TimeService.currentTimeMillis() - lastClearTime < PocConsensusConstant.CLEAR_INTERVAL_TIME) {
        return;
    }
    lastClearTime = TimeService.currentTimeMillis();
    // clear the master data
    clearMasterDatas();
    // clear the expired chain
    long bestHeight = chainManager.getBestBlockHeight();
    Iterator<ChainContainer> it = chainManager.getChains().iterator();
    while (it.hasNext()) {
        ChainContainer chain = it.next();
        if (checkChainIsExpired(chain, bestHeight)) {
            it.remove();
        }
    }
    it = chainManager.getOrphanChains().iterator();
    while (it.hasNext()) {
        ChainContainer orphanChain = it.next();
        if (checkChainIsExpired(orphanChain, bestHeight)) {
            it.remove();
        }
    }
}
Also used : ChainContainer(io.nuls.consensus.poc.container.ChainContainer)

Example 3 with ChainContainer

use of io.nuls.consensus.poc.container.ChainContainer in project nuls by nuls-io.

the class ForkChainProcess method printLog.

private void printLog() {
    time = System.currentTimeMillis();
    StringBuilder sb = new StringBuilder();
    sb.append("=========================\n");
    sb.append("Master Chain Status : \n");
    sb.append(getChainStatus(chainManager.getMasterChain()));
    sb.append("\n");
    List<ChainContainer> chains = chainManager.getChains();
    if (chains != null && chains.size() > 0) {
        sb.append("fork chains : \n");
        for (ChainContainer chain : chains) {
            sb.append(getChainStatus(chain));
        }
        sb.append("\n");
    }
    List<ChainContainer> iss = chainManager.getOrphanChains();
    if (iss != null && iss.size() > 0) {
        sb.append("orphan chains : \n");
        for (ChainContainer chain : iss) {
            sb.append(getChainStatus(chain));
        }
        sb.append("\n");
    }
    ChainLog.debug(sb.toString());
}
Also used : ChainContainer(io.nuls.consensus.poc.container.ChainContainer)

Example 4 with ChainContainer

use of io.nuls.consensus.poc.container.ChainContainer in project nuls by nuls-io.

the class ForkChainProcess method doProcess.

public boolean doProcess() throws IOException, NulsException {
    if (ConsensusStatusContext.getConsensusStatus().ordinal() < ConsensusStatus.RUNNING.ordinal()) {
        NulsContext.WALLET_STATUS = NulsConstant.SYNCHING;
        return false;
    }
    Lockers.CHAIN_LOCK.lock();
    try {
        printChainStatusLog();
        ChainContainer masterChain = chainManager.getMasterChain();
        if (null == masterChain) {
            return false;
        }
        // Monitor the status of the orphan chain, if it is available, join the verification chain
        // 监控孤立链的状态,如果有可连接的,则加入验证链里面
        monitorOrphanChains();
        BlockHeader masterBestHeader = masterChain.getBestBlock().getHeader();
        // 寻找可切换的链
        ChainContainer wantToChangeChain = findWantToChangeChain(masterBestHeader);
        if (wantToChangeChain != null) {
            NulsContext.WALLET_STATUS = NulsConstant.ROLLBACK;
            // 验证新的链,结合当前最新的链,获取到分叉节点时的状态
            ChainContainer resultChain = chainManager.getMasterChain().getBeforeTheForkChain(wantToChangeChain);
            List<Object[]> verifyResultList = new ArrayList<>();
            for (Block forkBlock : wantToChangeChain.getChain().getAllBlockList()) {
                Result success = resultChain.verifyAndAddBlock(forkBlock, true, false);
                if (success.isFailed()) {
                    resultChain = null;
                    break;
                } else {
                    verifyResultList.add((Object[]) success.getData());
                }
            }
            if (resultChain == null) {
                ChainLog.debug("verify the fork chain fail {} remove it", wantToChangeChain.getChain().getId());
                chainManager.getChains().remove(wantToChangeChain);
            } else {
                // Verify pass, try to switch chain
                // 验证通过,尝试切换链
                boolean success = changeChain(resultChain, wantToChangeChain, verifyResultList);
                if (success) {
                    chainManager.getChains().remove(wantToChangeChain);
                    /**
                     ********************************************************************************************************
                     */
                    try {
                        Log.info("");
                        Log.info("****************************************************");
                        Log.info("完成 切换连成功,获取当前bestblock, height:{},- {}", chainManager.getBestBlock().getHeader().getHeight(), chainManager.getBestBlock().getHeader().getHash());
                        Log.info("****************************************************");
                        Log.info("");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                /**
                 ********************************************************************************************************
                 */
                } else {
                    Log.info("切换链失败了---------------------------------");
                }
                ChainLog.debug("verify the fork chain {} success, change master chain result : {} , new master chain is {} : {} - {}", wantToChangeChain.getChain().getId(), success, chainManager.getBestBlock().getHeader().getHeight(), chainManager.getBestBlock().getHeader().getHash());
            }
        }
        clearExpiredChain();
    } finally {
        NulsContext.WALLET_STATUS = NulsConstant.RUNNING;
        Lockers.CHAIN_LOCK.unlock();
    }
    return true;
}
Also used : ChainContainer(io.nuls.consensus.poc.container.ChainContainer) IOException(java.io.IOException) NulsException(io.nuls.kernel.exception.NulsException) ContractResult(io.nuls.contract.dto.ContractResult) ValidateResult(io.nuls.kernel.validate.ValidateResult)

Example 5 with ChainContainer

use of io.nuls.consensus.poc.container.ChainContainer in project nuls by nuls-io.

the class OrphanBlockProcess method checkHasExist.

/*
     * Check the existence of this block from the forked chain and the isolated chain
     * 从分叉链和孤立链中检查,是否存在该区块
     */
private boolean checkHasExist(NulsDigestData blockHash) {
    for (Iterator<ChainContainer> it = chainManager.getOrphanChains().iterator(); it.hasNext(); ) {
        ChainContainer chainContainer = it.next();
        for (BlockHeader header : chainContainer.getChain().getAllBlockHeaderList()) {
            if (header.getHash().equals(blockHash)) {
                return true;
            }
        }
    }
    for (Iterator<ChainContainer> it = chainManager.getChains().iterator(); it.hasNext(); ) {
        ChainContainer chainContainer = it.next();
        for (BlockHeader header : chainContainer.getChain().getAllBlockHeaderList()) {
            if (header.getHash().equals(blockHash)) {
                return true;
            }
        }
    }
    List<BlockHeader> masterChainBlockHeaderList = chainManager.getMasterChain().getChain().getAllBlockHeaderList();
    int size = (int) (masterChainBlockHeaderList.size() - PocConsensusConstant.MAX_ISOLATED_BLOCK_COUNT * 1.05);
    if (size < 0) {
        size = 0;
    }
    for (int i = masterChainBlockHeaderList.size() - 1; i >= size; i--) {
        if (blockHash.equals(masterChainBlockHeaderList.get(i).getHash())) {
            return true;
        }
    }
    return false;
}
Also used : ChainContainer(io.nuls.consensus.poc.container.ChainContainer) BlockHeader(io.nuls.kernel.model.BlockHeader)

Aggregations

ChainContainer (io.nuls.consensus.poc.container.ChainContainer)17 Chain (io.nuls.consensus.poc.model.Chain)9 Block (io.nuls.kernel.model.Block)4 IOException (java.io.IOException)4 BaseTest (io.nuls.consensus.poc.BaseTest)3 NulsException (io.nuls.kernel.exception.NulsException)3 BlockHeader (io.nuls.kernel.model.BlockHeader)3 Test (org.junit.Test)3 Agent (io.nuls.consensus.poc.protocol.entity.Agent)2 Deposit (io.nuls.consensus.poc.protocol.entity.Deposit)2 ContractResult (io.nuls.contract.dto.ContractResult)2 NulsRuntimeException (io.nuls.kernel.exception.NulsRuntimeException)2 ValidateResult (io.nuls.kernel.validate.ValidateResult)2 CreateAgentTransaction (io.nuls.consensus.poc.protocol.tx.CreateAgentTransaction)1 DepositTransaction (io.nuls.consensus.poc.protocol.tx.DepositTransaction)1 PunishLogPo (io.nuls.consensus.poc.storage.po.PunishLogPo)1 PunishLogStorageService (io.nuls.consensus.poc.storage.service.PunishLogStorageService)1 ECKey (io.nuls.core.tools.crypto.ECKey)1 ArrayList (java.util.ArrayList)1