Coverage Summary for Class: NodeStatistics (org.ethereum.net)
Class |
Method, %
|
Line, %
|
NodeStatistics |
0%
(0/13)
|
0%
(0/60)
|
NodeStatistics$StatHandler |
0%
(0/4)
|
0%
(0/5)
|
Total |
0%
(0/17)
|
0%
(0/65)
|
1 /*
2 * This file is part of RskJ
3 * Copyright (C) 2017 RSK Labs Ltd.
4 * (derived from ethereumJ library, Copyright (c) 2016 <ether.camp>)
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 package org.ethereum.net;
21
22 import org.ethereum.net.eth.message.StatusMessage;
23 import org.ethereum.net.message.ReasonCode;
24 import org.ethereum.util.ByteUtil;
25
26 import java.math.BigInteger;
27 import java.util.concurrent.atomic.AtomicInteger;
28
29 import static java.lang.Math.min;
30
31 /**
32 * Handles all possible statistics related to a Node
33 * The primary aim of this is collecting info about a Node
34 * for maintaining its reputation.
35 *
36 * Created by Anton Nashatyrev on 16.07.2015.
37 */
38 public class NodeStatistics {
39 public static final int REPUTATION_PREDEFINED = 1000500;
40
41 private boolean isPredefined = false;
42
43 private int savedReputation = 0;
44
45 // discovery stat
46 public final StatHandler discoverOutPing = new StatHandler();
47 public final StatHandler discoverInPong = new StatHandler();
48 public final StatHandler discoverOutPong = new StatHandler();
49 public final StatHandler discoverInPing = new StatHandler();
50 public final StatHandler discoverInFind = new StatHandler();
51 public final StatHandler discoverOutFind = new StatHandler();
52 public final StatHandler discoverInNeighbours = new StatHandler();
53 public final StatHandler discoverOutNeighbours = new StatHandler();
54
55 // rlpx stat
56 public final StatHandler rlpxConnectionAttempts = new StatHandler();
57 public final StatHandler rlpxAuthMessagesSent = new StatHandler();
58 public final StatHandler rlpxOutHello = new StatHandler();
59 public final StatHandler rlpxInHello = new StatHandler();
60 public final StatHandler rlpxHandshake = new StatHandler();
61 public final StatHandler rlpxOutMessages = new StatHandler();
62 public final StatHandler rlpxInMessages = new StatHandler();
63
64 private String clientId = "";
65
66 private ReasonCode rlpxLastRemoteDisconnectReason = null;
67 private ReasonCode rlpxLastLocalDisconnectReason = null;
68 private boolean disconnected = false;
69
70 // Eth stat
71 public final StatHandler ethHandshake = new StatHandler();
72 private final StatHandler ethInbound = new StatHandler();
73 private final StatHandler ethOutbound = new StatHandler();
74 private StatusMessage ethLastInboundStatusMsg = null;
75 private BigInteger ethTotalDifficulty = BigInteger.ZERO;
76
77 int getSessionReputation() {
78 return getSessionFairReputation() + (isPredefined ? REPUTATION_PREDEFINED : 0);
79 }
80
81 int getSessionFairReputation() {
82 int discoverReput = 0;
83
84 discoverReput += min(discoverInPong.get(), 10) * (discoverOutPing.get() == discoverInPong.get() ? 2 : 1);
85 discoverReput += min(discoverInNeighbours.get(), 10) * 2;
86
87 int rlpxReput = 0;
88 rlpxReput += rlpxAuthMessagesSent.get() > 0 ? 10 : 0;
89 rlpxReput += rlpxHandshake.get() > 0 ? 20 : 0;
90 rlpxReput += min(rlpxInMessages.get(), 10) * 3;
91
92 if (disconnected) {
93 if (rlpxLastLocalDisconnectReason == null && rlpxLastRemoteDisconnectReason == null) {
94 // means connection was dropped without reporting any reason - bad
95 rlpxReput *= 0.3;
96 } else if (rlpxLastLocalDisconnectReason != ReasonCode.REQUESTED) {
97 // the disconnect was not initiated by discover mode
98 if (rlpxLastRemoteDisconnectReason == ReasonCode.TOO_MANY_PEERS) {
99 // The peer is popular, but we were unlucky
100 rlpxReput *= 0.8;
101 } else {
102 // other disconnect reasons
103 rlpxReput *= 0.5;
104 }
105 }
106 }
107
108 return discoverReput + 100 * rlpxReput;
109 }
110
111 public int getReputation() {
112 return savedReputation / 2 + getSessionReputation();
113 }
114
115 public void nodeDisconnectedRemote(ReasonCode reason) {
116 rlpxLastRemoteDisconnectReason = reason;
117 }
118
119 public void nodeDisconnectedLocal(ReasonCode reason) {
120 rlpxLastLocalDisconnectReason = reason;
121 }
122
123 public void ethHandshake(StatusMessage ethInboundStatus) {
124 this.ethLastInboundStatusMsg = ethInboundStatus;
125 this.ethTotalDifficulty = ethInboundStatus.getTotalDifficultyAsBigInt();
126 ethHandshake.add();
127 }
128
129 public BigInteger getEthTotalDifficulty() {
130 return ethTotalDifficulty;
131 }
132
133 public void setClientId(String clientId) {
134 this.clientId = clientId;
135 }
136
137 public void setPredefined(boolean isPredefined) {
138 this.isPredefined = isPredefined;
139 }
140
141 @Override
142 public String toString() {
143 return "NodeStat[reput: " + getReputation() + "(" + savedReputation + "), discover: " +
144 discoverInPong + "/" + discoverOutPing + " " +
145 discoverOutPong + "/" + discoverInPing + " " +
146 discoverInNeighbours + "/" + discoverOutFind + " " +
147 discoverOutNeighbours + "/" + discoverInFind + " " +
148 ", rlpx: " + rlpxHandshake + "/" + rlpxAuthMessagesSent + "/" + rlpxConnectionAttempts + " " +
149 rlpxInMessages + "/" + rlpxOutMessages +
150 ", eth: " + ethHandshake + "/" + getEthInbound() + "/" + getEthOutbound() + " " +
151 (ethLastInboundStatusMsg != null ? ByteUtil.toHexStringOrEmpty(ethLastInboundStatusMsg.getTotalDifficulty()) : "-") + " " +
152 (disconnected ? "X " : "") +
153 (rlpxLastLocalDisconnectReason != null ? ("<=" + rlpxLastLocalDisconnectReason) : " ") +
154 (rlpxLastRemoteDisconnectReason != null ? ("=>" + rlpxLastRemoteDisconnectReason) : " ") +
155 "[" + clientId + "]";
156 }
157
158 public StatHandler getEthInbound() {
159 return ethInbound;
160 }
161
162 public StatHandler getEthOutbound() {
163 return ethOutbound;
164 }
165
166 public class StatHandler {
167 AtomicInteger count = new AtomicInteger(0);
168 public void add() {count.incrementAndGet(); }
169 public int get() {return count.get();}
170 public String toString() {return count.toString();}
171 }
172 }