use of io.nuls.consensus.poc.container.ChainContainer in project nuls by nuls-io.
the class ForkChainProcess method monitorOrphanChains.
/**
* Monitor the orphan chain, if there is a connection with the main chain or the forked chain, the merged chain
* <p>
* 监控孤立链,如果有和主链或者分叉链连上的情况,则合并链
*/
private void monitorOrphanChains() {
List<ChainContainer> orphanChains = chainManager.getOrphanChains();
Iterator<ChainContainer> iterator = orphanChains.iterator();
while (iterator.hasNext()) {
ChainContainer orphanChain = iterator.next();
if (checkOrphanChainHasConnection(orphanChain)) {
iterator.remove();
}
}
}
use of io.nuls.consensus.poc.container.ChainContainer in project nuls by nuls-io.
the class ForkChainProcess method checkOrphanChainHasConnection.
private boolean checkOrphanChainHasConnection(ChainContainer orphanChain) {
// Determine whether the orphan chain is connected to the main chain
// 判断该孤立链是否和主链相连
BlockHeader startBlockHeader = orphanChain.getChain().getStartBlockHeader();
List<BlockHeader> blockHeaderList = chainManager.getMasterChain().getChain().getAllBlockHeaderList();
int count = blockHeaderList.size() > PocConsensusConstant.MAX_ISOLATED_BLOCK_COUNT ? PocConsensusConstant.MAX_ISOLATED_BLOCK_COUNT : blockHeaderList.size();
for (int i = blockHeaderList.size() - 1; i >= blockHeaderList.size() - count; i--) {
BlockHeader header = blockHeaderList.get(i);
if (startBlockHeader.getPreHash().equals(header.getHash()) && startBlockHeader.getHeight() == header.getHeight() + 1) {
// yes connectioned
orphanChain.getChain().setPreChainId(chainManager.getMasterChain().getChain().getId());
chainManager.getChains().add(orphanChain);
ChainLog.debug("discover the OrphanChain {} : start {} - {} , end {} - {} , connection the master chain of {} - {} - {}, move into the fork chians", orphanChain.getChain().getId(), startBlockHeader.getHeight(), startBlockHeader.getHash().getDigestHex(), orphanChain.getChain().getEndBlockHeader().getHeight(), orphanChain.getChain().getEndBlockHeader().getHash(), chainManager.getMasterChain().getChain().getId(), chainManager.getMasterChain().getChain().getBestBlock().getHeader().getHeight(), chainManager.getMasterChain().getChain().getBestBlock().getHeader().getHash());
return true;
} else if (startBlockHeader.getHeight() > header.getHeight()) {
break;
}
}
// 判断该孤链是否和待验证的分叉链相连
for (ChainContainer forkChain : chainManager.getChains()) {
Chain chain = forkChain.getChain();
if (startBlockHeader.getHeight() > chain.getEndBlockHeader().getHeight() + 1 || startBlockHeader.getHeight() <= chain.getStartBlockHeader().getHeight()) {
continue;
}
blockHeaderList = chain.getAllBlockHeaderList();
for (int i = 0; i < blockHeaderList.size(); i++) {
BlockHeader header = blockHeaderList.get(i);
if (startBlockHeader.getPreHash().equals(header.getHash()) && startBlockHeader.getHeight() == header.getHeight() + 1) {
// yes connectioned
orphanChain.getChain().setPreChainId(chain.getPreChainId());
// orphanChain.getChain().initData(chain.getStartBlockHeader(), blockHeaderList.subList(0, i + 1), chain.getAllBlockList().subList(0, i + 1));
List<Block> blockList = chain.getAllBlockList().subList(0, i + 1);
for (int m = blockList.size() - 1; m >= 0; m--) {
orphanChain.getChain().addPreBlock(blockList.get(m));
}
chainManager.getChains().add(orphanChain);
if (i == blockHeaderList.size() - 1) {
chainManager.getChains().remove(forkChain);
}
ChainLog.debug("discover the OrphanChain {} : start {} - {} , end {} - {} , connection the fork chain of : start {} - {} , end {} - {}, move into the fork chians", orphanChain.getChain().getId(), startBlockHeader.getHeight(), startBlockHeader.getHash().getDigestHex(), orphanChain.getChain().getEndBlockHeader().getHeight(), orphanChain.getChain().getEndBlockHeader().getHash(), chainManager.getMasterChain().getChain().getId(), chain.getStartBlockHeader().getHeight(), chain.getStartBlockHeader().getHash(), chain.getEndBlockHeader().getHeight(), chain.getEndBlockHeader().getHash());
return true;
} else if (startBlockHeader.getHeight() == header.getHeight() + 1) {
break;
}
}
}
// 判断孤立链之间是否相连
for (ChainContainer orphan : chainManager.getOrphanChains()) {
if (orphan.getChain().getEndBlockHeader().getHash().equals(orphanChain.getChain().getStartBlockHeader().getPreHash()) && orphan.getChain().getEndBlockHeader().getHeight() + 1 == orphanChain.getChain().getStartBlockHeader().getHeight()) {
// Chain chain = orphan.getChain();
// chain.initData(orphanChain.getChain().getEndBlockHeader(), orphanChain.getChain().getAllBlockHeaderList(), orphanChain.getChain().getAllBlockList());
Chain chain = orphan.getChain();
List<Block> blockList = orphanChain.getChain().getAllBlockList();
for (Block block : blockList) {
chain.addBlock(block);
}
return true;
}
}
return false;
}
use of io.nuls.consensus.poc.container.ChainContainer in project nuls by nuls-io.
the class ForkChainProcess method changeChain.
private boolean changeChain(ChainContainer newMasterChain, ChainContainer originalForkChain, List<Object[]> verifyResultList) throws NulsException, IOException {
if (newMasterChain == null || originalForkChain == null || verifyResultList == null) {
return false;
}
// Now the master chain, the forked chain after the switch, needs to be put into the list of chains to be verified.
// 现在的主链,在切换之后的分叉链,需要放入待验证链列表里面
ChainContainer oldChain = chainManager.getMasterChain().getAfterTheForkChain(originalForkChain);
// rollbackTransaction
List<Block> rollbackBlockList = oldChain.getChain().getAllBlockList();
ChainLog.debug("rollbackTransaction the master chain , need rollbackTransaction block count is {}, master chain is {} : {} - {} , service best block : {} - {}", rollbackBlockList.size(), chainManager.getMasterChain().getChain().getId(), chainManager.getBestBlock().getHeader().getHeight(), chainManager.getBestBlock().getHeader().getHash(), blockService.getBestBlock().getData().getHeader().getHeight(), blockService.getBestBlock().getData().getHeader().getHash());
// Need descending order
// 需要降序排列
Collections.reverse(rollbackBlockList);
if (rollbackBlockList != null && rollbackBlockList.size() > 0 && rollbackBlockList.get(0).getHeader().getHeight() != chainManager.getMasterChain().getBestBlock().getHeader().getHeight()) {
Log.error("------------------------回滚的起始高度不是主链最新高度");
Log.error("----------------------- masterChain:" + chainManager.getMasterChain().getBestBlock().getHeader().getHeight() + ",hash:" + chainManager.getMasterChain().getBestBlock().getHeader().getHash().getDigestHex());
Log.error("----------------------- rollbackBlockList:" + rollbackBlockList.get(0).getHeader().getHeight() + ",hash:" + rollbackBlockList.get(0).getHeader().getHash().getDigestHex());
}
boolean rollbackResult = rollbackBlocks(rollbackBlockList);
if (!rollbackResult) {
return false;
}
boolean changeSuccess = true;
List<Block> successList = new ArrayList<>();
try {
changeSuccess = doChange(successList, originalForkChain, verifyResultList);
} catch (Exception e) {
Log.error(e);
changeSuccess = false;
}
ChainLog.debug("add new blocks complete, result {}, success count is {} , now service best block : {} - {}", changeSuccess, successList.size(), blockService.getBestBlock().getData().getHeader().getHeight(), blockService.getBestBlock().getData().getHeader().getHash());
if (changeSuccess) {
chainManager.setMasterChain(newMasterChain);
newMasterChain.initRound();
NulsContext.getInstance().setBestBlock(newMasterChain.getBestBlock());
if (oldChain.getChain().getAllBlockList().size() > 0) {
Collections.reverse(rollbackBlockList);
chainManager.getChains().add(oldChain);
}
} else {
// Fallback status
// 回退状态
Collections.reverse(successList);
for (Block rollBlock : successList) {
Result rs = blockService.rollbackBlock(rollBlock);
if (rs.isSuccess()) {
// 回滚版本更新统计数据
nulsProtocolProcess.processProtocolRollback(rollBlock.getHeader());
randomSeedService.rollbackBlock(rollBlock.getHeader());
}
RewardStatisticsProcess.rollbackBlock(rollBlock);
}
Collections.reverse(rollbackBlockList);
for (Block addBlock : rollbackBlockList) {
nulsProtocolProcess.processProtocolUpGrade(addBlock.getHeader());
Result rs = blockService.saveBlock(addBlock);
if (!rs.isSuccess()) {
nulsProtocolProcess.processProtocolRollback(addBlock.getHeader());
}
RewardStatisticsProcess.addBlock(addBlock);
}
}
return changeSuccess;
}
use of io.nuls.consensus.poc.container.ChainContainer in project nuls by nuls-io.
the class ChainManagerTest method testCheckIsBeforeOrphanChainAndAdd.
@Test
public void testCheckIsBeforeOrphanChainAndAdd() {
testGetBestBlockHeight();
Block block = createBlock();
Block block1 = createBlock();
block1.getHeader().setHeight(1L);
block1.getHeader().setPreHash(block.getHeader().getHash());
ChainContainer orphanChain = new ChainContainer(new Chain());
orphanChain.getChain().addBlock(block1);
chainManager.getOrphanChains().add(orphanChain);
assertEquals(1, chainManager.getOrphanChains().size());
boolean success = chainManager.checkIsBeforeOrphanChainAndAdd(block);
assertTrue(success);
}
use of io.nuls.consensus.poc.container.ChainContainer in project nuls by nuls-io.
the class ChainManager method newOrphanChain.
public void newOrphanChain(Block block) {
Chain orphanChain = new Chain();
orphanChain.initData(block);
ChainContainer orphanChainContainer = new ChainContainer(orphanChain);
orphanChains.add(orphanChainContainer);
}
Aggregations