Changeset View
Changeset View
Standalone View
Standalone View
src/avalanche/peermanager.cpp
Show First 20 Lines • Show All 158 Lines • ▼ Show 20 Lines | bool PeerManager::updateNextPossibleConflictTime( | ||||
peers.modify(it, [&](Peer &p) { | peers.modify(it, [&](Peer &p) { | ||||
p.nextPossibleConflictTime = | p.nextPossibleConflictTime = | ||||
std::max(p.nextPossibleConflictTime, nextTime); | std::max(p.nextPossibleConflictTime, nextTime); | ||||
}); | }); | ||||
return it->nextPossibleConflictTime == nextTime; | return it->nextPossibleConflictTime == nextTime; | ||||
} | } | ||||
bool PeerManager::registerProof(const ProofRef &proof, RegistrationMode mode) { | bool PeerManager::registerProof(const ProofRef &proof, | ||||
ProofRegistrationState ®istrationState, | |||||
RegistrationMode mode) { | |||||
assert(proof); | assert(proof); | ||||
const ProofId &proofid = proof->getId(); | const ProofId &proofid = proof->getId(); | ||||
auto invalidate = [&](ProofRegistrationResult result, | |||||
const std::string &message) { | |||||
return registrationState.Invalid( | |||||
result, message, strprintf("proofid: %s", proofid.ToString())); | |||||
}; | |||||
if ((mode != RegistrationMode::FORCE_ACCEPT || | if ((mode != RegistrationMode::FORCE_ACCEPT || | ||||
!isInConflictingPool(proofid)) && | !isInConflictingPool(proofid)) && | ||||
exists(proofid)) { | exists(proofid)) { | ||||
// In default mode, we expect the proof to be unknown, i.e. in none of | // In default mode, we expect the proof to be unknown, i.e. in none of | ||||
// the pools. | // the pools. | ||||
// In forced accept mode, the proof can be in the conflicting pool. | // In forced accept mode, the proof can be in the conflicting pool. | ||||
return false; | return invalidate(ProofRegistrationResult::ALREADY_REGISTERED, | ||||
"proof-already-registered"); | |||||
} | } | ||||
// Check the proof's validity. | // Check the proof's validity. | ||||
ProofValidationState state; | ProofValidationState validationState; | ||||
// Using WITH_LOCK directly inside the if statement will trigger a cppcheck | // Using WITH_LOCK directly inside the if statement will trigger a cppcheck | ||||
// false positive syntax error | // false positive syntax error | ||||
const bool valid = WITH_LOCK( | const bool valid = WITH_LOCK( | ||||
cs_main, return proof->verify(state, ::ChainstateActive().CoinsTip())); | cs_main, | ||||
return proof->verify(validationState, ::ChainstateActive().CoinsTip())); | |||||
if (!valid) { | if (!valid) { | ||||
if (isOrphanState(state)) { | if (isOrphanState(validationState)) { | ||||
orphanProofPool.addProofIfPreferred(proof); | orphanProofPool.addProofIfPreferred(proof); | ||||
return invalidate(ProofRegistrationResult::ORPHAN, "orphan-proof"); | |||||
} | } | ||||
// Reject invalid proof. | // Reject invalid proof. | ||||
return false; | return invalidate(ProofRegistrationResult::INVALID, "invalid-proof"); | ||||
} | } | ||||
ProofPool::ConflictingProofSet conflictingProofs; | ProofPool::ConflictingProofSet conflictingProofs; | ||||
switch (validProofPool.addProofIfNoConflict(proof, conflictingProofs)) { | switch (validProofPool.addProofIfNoConflict(proof, conflictingProofs)) { | ||||
case ProofPool::AddProofStatus::REJECTED: { | case ProofPool::AddProofStatus::REJECTED: { | ||||
if (mode != RegistrationMode::FORCE_ACCEPT) { | if (mode != RegistrationMode::FORCE_ACCEPT) { | ||||
// The proof has conflicts, move it to the conflicting proof | // The proof has conflicts, move it to the conflicting proof | ||||
// pool so it can be pulled back if the conflicting ones are | // pool so it can be pulled back if the conflicting ones are | ||||
// invalidated. | // invalidated. | ||||
conflictingProofPool.addProofIfPreferred(proof); | return conflictingProofPool.addProofIfPreferred(proof) == | ||||
return false; | ProofPool::AddProofStatus::REJECTED | ||||
? invalidate(ProofRegistrationResult::REJECTED, | |||||
"rejected-proof") | |||||
: invalidate(ProofRegistrationResult::CONFLICTING, | |||||
"conflicting-utxos"); | |||||
} | } | ||||
conflictingProofPool.removeProof(proofid); | conflictingProofPool.removeProof(proofid); | ||||
// Move the conflicting proofs from the valid pool to the | // Move the conflicting proofs from the valid pool to the | ||||
// conflicting pool | // conflicting pool | ||||
auto &peersView = peers.get<by_proofid>(); | auto &peersView = peers.get<by_proofid>(); | ||||
for (const ProofRef &conflictingProof : conflictingProofs) { | for (const ProofRef &conflictingProof : conflictingProofs) { | ||||
auto it = peersView.find(conflictingProof->getId()); | auto it = peersView.find(conflictingProof->getId()); | ||||
if (it != peersView.end()) { | if (it != peersView.end()) { | ||||
removePeer(it->peerid); | removePeer(it->peerid); | ||||
} | } | ||||
conflictingProofPool.addProofIfPreferred(conflictingProof); | conflictingProofPool.addProofIfPreferred(conflictingProof); | ||||
} | } | ||||
auto status = validProofPool.addProofIfNoConflict(proof); | auto status = validProofPool.addProofIfNoConflict(proof); | ||||
assert(status == ProofPool::AddProofStatus::SUCCEED); | assert(status == ProofPool::AddProofStatus::SUCCEED); | ||||
break; | break; | ||||
} | } | ||||
case ProofPool::AddProofStatus::DUPLICATED: | case ProofPool::AddProofStatus::DUPLICATED: | ||||
// If the proof was already in the pool, don't duplicate the peer. | // If the proof was already in the pool, don't duplicate the peer. | ||||
return false; | return invalidate(ProofRegistrationResult::ALREADY_REGISTERED, | ||||
"proof-already-registered"); | |||||
case ProofPool::AddProofStatus::SUCCEED: | case ProofPool::AddProofStatus::SUCCEED: | ||||
break; | break; | ||||
// No default case, so the compiler can warn about missing cases | // No default case, so the compiler can warn about missing cases | ||||
} | } | ||||
// At this stage we are going to create a peer so the proof should never | // At this stage we are going to create a peer so the proof should never | ||||
// exist in the conflicting pool, but use belt and suspenders. | // exist in the conflicting pool, but use belt and suspenders. | ||||
▲ Show 20 Lines • Show All 379 Lines • Show Last 20 Lines |