| 3114 | } |
| 3115 | |
| 3116 | void PeerLogicValidation::ConsiderEviction(CNode *pto, int64_t time_in_seconds) |
| 3117 | { |
| 3118 | AssertLockHeld(cs_main); |
| 3119 | |
| 3120 | CNodeState &state = *State(pto->GetId()); |
| 3121 | const CNetMsgMaker msgMaker(pto->GetSendVersion()); |
| 3122 | |
| 3123 | if (!state.m_chain_sync.m_protect && IsOutboundDisconnectionCandidate(pto) && state.fSyncStarted) { |
| 3124 | // This is an outbound peer subject to disconnection if they don't |
| 3125 | // announce a block with as much work as the current tip within |
| 3126 | // CHAIN_SYNC_TIMEOUT + HEADERS_RESPONSE_TIME seconds (note: if |
| 3127 | // their chain has more work than ours, we should sync to it, |
| 3128 | // unless it's invalid, in which case we should find that out and |
| 3129 | // disconnect from them elsewhere). |
| 3130 | if (state.pindexBestKnownBlock != nullptr && state.pindexBestKnownBlock->nChainWork >= chainActive.Tip()->nChainWork) { |
| 3131 | if (state.m_chain_sync.m_timeout != 0) { |
| 3132 | state.m_chain_sync.m_timeout = 0; |
| 3133 | state.m_chain_sync.m_work_header = nullptr; |
| 3134 | state.m_chain_sync.m_sent_getheaders = false; |
| 3135 | } |
| 3136 | } else if (state.m_chain_sync.m_timeout == 0 || (state.m_chain_sync.m_work_header != nullptr && state.pindexBestKnownBlock != nullptr && state.pindexBestKnownBlock->nChainWork >= state.m_chain_sync.m_work_header->nChainWork)) { |
| 3137 | // Our best block known by this peer is behind our tip, and we're either noticing |
| 3138 | // that for the first time, OR this peer was able to catch up to some earlier point |
| 3139 | // where we checked against our tip. |
| 3140 | // Either way, set a new timeout based on current tip. |
| 3141 | state.m_chain_sync.m_timeout = time_in_seconds + CHAIN_SYNC_TIMEOUT; |
| 3142 | state.m_chain_sync.m_work_header = chainActive.Tip(); |
| 3143 | state.m_chain_sync.m_sent_getheaders = false; |
| 3144 | } else if (state.m_chain_sync.m_timeout > 0 && time_in_seconds > state.m_chain_sync.m_timeout) { |
| 3145 | // No evidence yet that our peer has synced to a chain with work equal to that |
| 3146 | // of our tip, when we first detected it was behind. Send a single getheaders |
| 3147 | // message to give the peer a chance to update us. |
| 3148 | if (state.m_chain_sync.m_sent_getheaders) { |
| 3149 | // They've run out of time to catch up! |
| 3150 | LogPrintf("Disconnecting outbound peer %d for old chain, best known block = %s\n", pto->GetId(), state.pindexBestKnownBlock != nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() : "<none>"); |
| 3151 | pto->fDisconnect = true; |
| 3152 | } else { |
| 3153 | assert(state.m_chain_sync.m_work_header); |
| 3154 | LogPrint(BCLog::NET, "sending getheaders to outbound peer=%d to verify chain work (current best known block:%s, benchmark blockhash: %s)\n", pto->GetId(), state.pindexBestKnownBlock != nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() : "<none>", state.m_chain_sync.m_work_header->GetBlockHash().ToString()); |
| 3155 | connman->PushMessage(pto, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(state.m_chain_sync.m_work_header->pprev), uint256())); |
| 3156 | state.m_chain_sync.m_sent_getheaders = true; |
| 3157 | constexpr int64_t HEADERS_RESPONSE_TIME = 120; // 2 minutes |
| 3158 | // Bump the timeout to allow a response, which could clear the timeout |
| 3159 | // (if the response shows the peer has synced), reset the timeout (if |
| 3160 | // the peer syncs to the required work but not to our tip), or result |
| 3161 | // in disconnect (if we advance to the timeout and pindexBestKnownBlock |
| 3162 | // has not sufficiently progressed) |
| 3163 | state.m_chain_sync.m_timeout = time_in_seconds + HEADERS_RESPONSE_TIME; |
| 3164 | } |
| 3165 | } |
| 3166 | } |
| 3167 | } |
| 3168 | |
| 3169 | void PeerLogicValidation::EvictExtraOutboundPeers(int64_t time_in_seconds) |
| 3170 | { |
nothing calls this directly
no test coverage detected