last_restarted in server_status is wrongly calculated
Looking at https://metrics.torproject.org/rs.html#details/0111BA9B604669E636FFD5B503F382A4B7AD6E80 I can see right now that the relay got last restarted 2024-06-13 18:13:41. However, checking in our DB I get the following:
+------------------------------------------+--------------------------------------------+----------------------+----------------------+
| fingerprint | nickname | first_seen | last_restarted |
+------------------------------------------+--------------------------------------------+----------------------+----------------------+
| 0111BA9B604669E636FFD5B503F382A4B7AD6E80 | DigiGesTor1e1 | 2024-03-30 19:00:00 | 2024-06-13 18:59:40 |
| 0111BA9B604669E636FFD5B503F382A4B7AD6E80 | DigiGesTor1e1 | 2024-03-30 19:00:00 | 2024-06-13 18:59:57 |
| 0111BA9B604669E636FFD5B503F382A4B7AD6E80 | DigiGesTor1e1 | 2024-03-30 19:00:00 | 2024-06-13 19:59:40 |
| 0111BA9B604669E636FFD5B503F382A4B7AD6E80 | DigiGesTor1e1 | 2024-03-30 19:00:00 | 2024-06-13 19:59:57 |
| 0111BA9B604669E636FFD5B503F382A4B7AD6E80 | DigiGesTor1e1 | 2024-03-30 19:00:00 | 2024-06-13 20:59:40 |
| 0111BA9B604669E636FFD5B503F382A4B7AD6E80 | DigiGesTor1e1 | 2024-03-30 19:00:00 | 2024-06-13 20:59:57 |
| 0111BA9B604669E636FFD5B503F382A4B7AD6E80 | DigiGesTor1e1 | 2024-03-30 19:00:00 | 2024-06-13 21:59:57 |
| 0111BA9B604669E636FFD5B503F382A4B7AD6E80 | DigiGesTor1e1 | 2024-03-30 19:00:00 | 2024-06-13 22:59:57 |
| 0111BA9B604669E636FFD5B503F382A4B7AD6E80 | DigiGesTor1e1 | 2024-03-30 19:00:00 | 2024-06-13 23:59:57 |
FWIW, that's not just for that relay. For others there is a large amount of changes in last restart times visible as well, e.g.:
| 000A10D43011EA4928A35F610405F92B4433B4DC | seele | 2024-03-30 20:00:00 | 2024-06-13 00:59:30 |
| 000A10D43011EA4928A35F610405F92B4433B4DC | seele | 2024-03-30 20:00:00 | 2024-06-13 00:59:37 |
| 000A10D43011EA4928A35F610405F92B4433B4DC | seele | 2024-03-30 20:00:00 | 2024-06-13 00:59:58 |
| 000A10D43011EA4928A35F610405F92B4433B4DC | seele | 2024-03-30 20:00:00 | 2024-06-13 01:59:30 |
| 000A10D43011EA4928A35F610405F92B4433B4DC | seele | 2024-03-30 20:00:00 | 2024-06-13 01:59:37 |
| 000A10D43011EA4928A35F610405F92B4433B4DC | seele | 2024-03-30 20:00:00 | 2024-06-13 01:59:58 |
| 000A10D43011EA4928A35F610405F92B4433B4DC | seele | 2024-03-30 20:00:00 | 2024-06-13 02:59:30 |
| 000A10D43011EA4928A35F610405F92B4433B4DC | seele | 2024-03-30 20:00:00 | 2024-06-13 02:59:37 |
| 000A10D43011EA4928A35F610405F92B4433B4DC | seele | 2024-03-30 20:00:00 | 2024-06-13 02:59:58 |
| 000A10D43011EA4928A35F610405F92B4433B4DC | seele | 2024-03-30 20:00:00 | 2024-06-13 03:59:37 |
| 000A10D43011EA4928A35F610405F92B4433B4DC | seele | 2024-03-30 20:00:00 | 2024-06-13 03:59:58 |
| 000A10D43011EA4928A35F610405F92B4433B4DC | seele | 2024-03-30 20:00:00 | 2024-06-13 04:59:37 |
| 000A10D43011EA4928A35F610405F92B4433B4DC | seele | 2024-03-30 20:00:00 | 2024-06-13 04:59:58 |
| 000A10D43011EA4928A35F610405F92B4433B4DC | seele | 2024-03-30 20:00:00 | 2024-06-13 05:59:37 |
| 000A10D43011EA4928A35F610405F92B4433B4DC | seele | 2024-03-30 20:00:00 | 2024-06-13 05:59:58 |
| 000A10D43011EA4928A35F610405F92B4433B4DC | seele | 2024-03-30 20:00:00 | 2024-06-13 06:59:37 |
| 000A10D43011EA4928A35F610405F92B4433B4DC | seele | 2024-03-30 20:00:00 | 2024-06-13 06:59:58 |
| 000A10D43011EA4928A35F610405F92B4433B4DC | seele | 2024-03-30 20:00:00 | 2024-06-13 07:59:58 |
| 000A10D43011EA4928A35F610405F92B4433B4DC | seele | 2024-03-30 20:00:00 | 2024-06-13 08:59:58 |
| 000A10D43011EA4928A35F610405F92B4433B4DC | seele | 2024-03-30 20:00:00 | 2024-06-13 09:59:58 |
| 000A10D43011EA4928A35F610405F92B4433B4DC | seele | 2024-03-30 20:00:00 | 2024-06-13 10:59:58 |
The code we have responsible for the last restart computation is:
private Long calculateLastRestartedMillis(RouterStatus routerStatus) {
Long lastRestartedMillis = 0L;
if (routerStatus.getUptime() != -1L) {
lastRestartedMillis = routerStatus.getLastSeenMillis()
- routerStatus.getUptime() * DateTimeHelper.ONE_SECOND;
}
return lastRestartedMillis;
}
The last_seen
field of a router status is set right at the status initialization to the time when the consensus becomes valid (via routerStatus.setLastSeenMillis(desc.getValidAfterMillis());
), so that changes every hour. However, there is no hourly server descriptor with a similar uptime change: so, the lastRestartedMillis
start to change every hour as well, which is not expected. In short, making the date for restarting the router the last time dependent on when it was last seen in the consensus is wrong.
Instead last_restarted
needs to take the publishing time of the server descriptor into account and subtract the contained uptime. Onionoo is doing it right:
private Long calculateLastRestartedMillis(ServerDescriptor descriptor) {
Long lastRestartedMillis = null;
if (null != descriptor.getUptime()) {
lastRestartedMillis = descriptor.getPublishedMillis()
- descriptor.getUptime() * DateTimeHelper.ONE_SECOND;
}
return lastRestartedMillis;