diff --git a/src/main/java/bftsmart/consensus/roles/Acceptor.java b/src/main/java/bftsmart/consensus/roles/Acceptor.java index 453370907c0bebcdb21673b8b9fd9660f0a0a1d7..4c092c7a010f2b4f1b046db00aa918dd18e7f24a 100644 --- a/src/main/java/bftsmart/consensus/roles/Acceptor.java +++ b/src/main/java/bftsmart/consensus/roles/Acceptor.java @@ -195,12 +195,19 @@ public final class Acceptor { */ public final void processMessage(ConsensusMessage msg) { Consensus consensus = executionManager.getConsensus(msg.getNumber()); + + // 该版本添加特殊处理,后续需要考虑优化掉该处理 + if (msg.getType() != MessageFactory.PROPOSE && consensus.getLastEpoch() != null && consensus.getLastEpoch().getTimestamp() > msg.getEpoch()) { + msg = new ConsensusMessage(msg.getType(),msg.getNumber(),consensus.getLastEpoch().getTimestamp(), msg.getSender(), msg.getValue()); + } + // 检查消息的epoch if (!checkSucc(consensus, msg.getEpoch())) { - LOGGER.info("I am proc {}, processMessage checkSucc failed!", topology.getStaticConf().getProcessId()); + LOGGER.info("I am proc {}, msg type = {}, processMessage checkSucc failed!", topology.getStaticConf().getProcessId(), msg.getType()); return; } + // 收到的共识消息对应的时间戳 Epoch poch = consensus.getEpoch(msg.getEpoch(), topology); diff --git a/src/main/java/bftsmart/tom/core/Synchronizer.java b/src/main/java/bftsmart/tom/core/Synchronizer.java index 576b38c8b3149bf945050d72944a3b6b93e17b9c..e7e19ea50f4cab876081292cc8ee9144d5b88e58 100644 --- a/src/main/java/bftsmart/tom/core/Synchronizer.java +++ b/src/main/java/bftsmart/tom/core/Synchronizer.java @@ -1617,6 +1617,9 @@ public class Synchronizer { } // 通过重新发送共识消息,触发落后节点的交易处理,不能简单的只进行cons.decided, 并且使用新的epoch时间戳,否则共识消息会因为时间戳不匹配被丢掉 + // 风险1:如果别的节点lastcid == lastHighestCID, 则不会走到这一步,也不会再发送共识ID为lastHighestCID的Write消息,那么在LC的最后阶段该节点也无法完成未完成的共识,后续该节点就落后了; + // 风险2:上一步放入stop消息队列的共识证据消息只包括Accept类型,没有Write阶段处理只能进入Accept阶段也会发生异常; + // 目前暂时通过放宽Accept类中对共识消息时间戳检测来解决该问题; recoveryConsensus(lastHighestCID.getCID(), latestEpoch); } else {