@@ -959,27 +959,68 @@ void Misbehaving(NodeId pnode, int howmuch, const std::string& message) EXCLUSIV
959959 LogPrint (BCLog::NET, " %s: %s peer=%d (%d -> %d)%s\n " , __func__, state->name , pnode, state->nMisbehavior -howmuch, state->nMisbehavior , message_prefixed);
960960}
961961
962+ /* *
963+ * Returns true if the given validation state result may result in a peer
964+ * banning/disconnecting us. We use this to determine which unaccepted
965+ * transactions from a whitelisted peer that we can safely relay.
966+ */
962967static bool TxRelayMayResultInDisconnect (const CValidationState& state)
963968{
964- return ( state.GetDoS () > 0 ) ;
969+ return state.GetReason () == ValidationInvalidReason::CONSENSUS ;
965970}
966971
967972/* *
968973 * Potentially ban a node based on the contents of a CValidationState object
969- * TODO: net_processing should make the punish decision based on the reason
970- * a tx/block was invalid, rather than just the nDoS score handed back by validation.
971974 *
972- * @parameter via_compact_block: this bool is passed in because net_processing should
975+ * @param[in] via_compact_block: this bool is passed in because net_processing should
973976 * punish peers differently depending on whether the data was provided in a compact
974977 * block message or not. If the compact block had a valid header, but contained invalid
975978 * txs, the peer should not be punished. See BIP 152.
979+ *
980+ * @return Returns true if the peer was punished (probably disconnected)
981+ *
982+ * Changes here may need to be reflected in TxRelayMayResultInDisconnect().
976983 */
977984static bool MaybePunishNode (NodeId nodeid, const CValidationState& state, bool via_compact_block, const std::string& message = " " ) {
978- int nDoS = state.GetDoS ();
979- if (nDoS > 0 && !via_compact_block) {
980- LOCK (cs_main);
981- Misbehaving (nodeid, nDoS, message);
982- return true ;
985+ switch (state.GetReason ()) {
986+ case ValidationInvalidReason::NONE:
987+ break ;
988+ // The node is providing invalid data:
989+ case ValidationInvalidReason::CONSENSUS:
990+ case ValidationInvalidReason::BLOCK_MUTATED:
991+ if (!via_compact_block) {
992+ LOCK (cs_main);
993+ Misbehaving (nodeid, 100 , message);
994+ return true ;
995+ }
996+ break ;
997+ // Handled elsewhere for now
998+ case ValidationInvalidReason::CACHED_INVALID:
999+ break ;
1000+ case ValidationInvalidReason::BLOCK_INVALID_HEADER:
1001+ case ValidationInvalidReason::BLOCK_CHECKPOINT:
1002+ case ValidationInvalidReason::BLOCK_INVALID_PREV:
1003+ {
1004+ LOCK (cs_main);
1005+ Misbehaving (nodeid, 100 , message);
1006+ }
1007+ return true ;
1008+ // Conflicting (but not necessarily invalid) data or different policy:
1009+ case ValidationInvalidReason::BLOCK_MISSING_PREV:
1010+ {
1011+ // TODO: Handle this much more gracefully (10 DoS points is super arbitrary)
1012+ LOCK (cs_main);
1013+ Misbehaving (nodeid, 10 , message);
1014+ }
1015+ return true ;
1016+ case ValidationInvalidReason::RECENT_CONSENSUS_CHANGE:
1017+ case ValidationInvalidReason::BLOCK_TIME_FUTURE:
1018+ case ValidationInvalidReason::TX_NOT_STANDARD:
1019+ case ValidationInvalidReason::TX_MISSING_INPUTS:
1020+ case ValidationInvalidReason::TX_WITNESS_MUTATED:
1021+ case ValidationInvalidReason::TX_CONFLICT:
1022+ case ValidationInvalidReason::TX_MEMPOOL_POLICY:
1023+ break ;
9831024 }
9841025 if (message != " " ) {
9851026 LogPrint (BCLog::NET, " peer=%d: %s\n " , nodeid, message);
@@ -2513,14 +2554,13 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
25132554 // to policy, allowing the node to function as a gateway for
25142555 // nodes hidden behind it.
25152556 //
2516- // Never relay transactions that we would assign a non-zero DoS
2517- // score for, as we expect peers to do the same with us in that
2518- // case.
2519- if (!state.IsInvalid () || !TxRelayMayResultInDisconnect (state)) {
2557+ // Never relay transactions that might result in being
2558+ // disconnected (or banned).
2559+ if (state.IsInvalid () && TxRelayMayResultInDisconnect (state)) {
2560+ LogPrintf (" Not relaying invalid transaction %s from whitelisted peer=%d (%s)\n " , tx.GetHash ().ToString (), pfrom->GetId (), FormatStateMessage (state));
2561+ } else {
25202562 LogPrintf (" Force relaying tx %s from whitelisted peer=%d\n " , tx.GetHash ().ToString (), pfrom->GetId ());
25212563 RelayTransaction (tx, connman);
2522- } else {
2523- LogPrintf (" Not relaying invalid transaction %s from whitelisted peer=%d (%s)\n " , tx.GetHash ().ToString (), pfrom->GetId (), FormatStateMessage (state));
25242564 }
25252565 }
25262566 }
@@ -2590,21 +2630,8 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
25902630 const CBlockIndex *pindex = nullptr ;
25912631 CValidationState state;
25922632 if (!ProcessNewBlockHeaders ({cmpctblock.header }, state, chainparams, &pindex)) {
2593- if (state.IsInvalid () && received_new_header) {
2594- // In this situation, the block header is known to be invalid.
2595- // If we never created a CBlockIndex entry for it, then the
2596- // header must be bad just by inspection (and is not one that
2597- // looked okay but the block later turned out to be invalid for
2598- // some other reason).
2599- // We should punish compact block peers that give us an invalid
2600- // header (other than a "duplicate-invalid" one, see
2601- // ProcessHeadersMessage), so set via_compact_block to false
2602- // here.
2603- // TODO: when we switch from DoS scores to reasons that
2604- // tx/blocks are invalid, this call should set
2605- // via_compact_block to true, since MaybePunishNode will have
2606- // sufficient information to act correctly.
2607- MaybePunishNode (pfrom->GetId (), state, /* via_compact_block*/ false , " invalid header via cmpctblock" );
2633+ if (state.IsInvalid ()) {
2634+ MaybePunishNode (pfrom->GetId (), state, /* via_compact_block*/ true , " invalid header via cmpctblock" );
26082635 return true ;
26092636 }
26102637 }
0 commit comments