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;
}
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();
}
}
}
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());
}
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;
}
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;
}
Aggregations