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
}
}