1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
crate::ix!();
pub trait MaybePunishNodeForBlock {
fn maybe_punish_node_for_block(&self,
nodeid: NodeId,
state: &BlockValidationState,
via_compact_block: bool,
message: Option<&str>) -> bool;
}
impl MaybePunishNodeForBlock for PeerManager {
/**
| Potentially mark a node discouraged
| based on the contents of a BlockValidationState
| object
|
| -----------
| @param[in] via_compact_block
|
| this bool is passed in because net_processing
| should punish peers differently depending
| on whether the data was provided in a
| compact block message or not. If the
| compact block had a valid header, but
| contained invalid txs, the peer should
| not be punished. See BIP 152.
|
| -----------
| @return
|
| Returns true if the peer was punished
| (probably disconnected)
|
*/
fn maybe_punish_node_for_block(&self,
nodeid: NodeId,
state: &BlockValidationState,
via_compact_block: bool,
message: Option<&str>) -> bool {
let message: &str = message.unwrap_or("");
match state.get_result() {
BlockValidationResult::BLOCK_RESULT_UNSET => { },
BlockValidationResult::BLOCK_CONSENSUS
| BlockValidationResult::BLOCK_MUTATED => {
// The node is providing invalid data:
if !via_compact_block {
self.misbehaving(nodeid, 100, message);
return true;
}
},
BlockValidationResult::BLOCK_CACHED_INVALID => {
let mut guard = CS_MAIN.lock();
let node_state: Amo<NodeState> = create_state(nodeid);
if node_state.is_some() {
// Discourage outbound (but not
// inbound) peers if on an invalid
// chain.
//
// Exempt HB compact block
// peers. Manual connections are
// always protected from
// discouragement.
if !via_compact_block && !node_state.get().is_inbound.load(atomic::Ordering::Relaxed) {
self.misbehaving(nodeid, 100, message);
return true;
}
}
},
BlockValidationResult::BLOCK_INVALID_HEADER
| BlockValidationResult::BLOCK_CHECKPOINT
| BlockValidationResult::BLOCK_INVALID_PREV => {
self.misbehaving(nodeid, 100, message);
return true;
},
// Conflicting (but not necessarily
// invalid) data or different policy:
BlockValidationResult::BLOCK_MISSING_PREV => {
// TODO: Handle this much more
// gracefully (10 DoS points is
// super arbitrary)
self.misbehaving(nodeid,10,message);
return true;
},
BlockValidationResult::BLOCK_RECENT_CONSENSUS_CHANGE
| BlockValidationResult::BLOCK_TIME_FUTURE => { },
}
if message != "" {
log_print!(LogFlags::NET, "peer=%d: %s\n", nodeid, message);
}
false
}
}