The ghetto version was not even remotely similar to a string view, but
was actually a string iterator pair container with no ability to
actually "view" anything.
- Enforce hex rather than accepting any random 66- or 64-character
string as a pubkey
- Clean up pubkey -> integer code
- The cleanup fixes a bug where pubkey -> integer conversion was
skipping the first two bytes on testnet (and ended up in UB by reading
the null + one byte beyond the end of the string for testnet
addresses). THIS WILL BREAK EXISTING TESTNET PUBKEY->SWARM VALUES!
(but it's only testnet, so that's okay).
The protocol is currently underdesigned with no failure mechanism at
all, so there's nothing we *can* fix here. We should fix the protocol,
of course, but that's outside the scope of this PR.
SS's current testee/tester sorting is based on (nasty) sorting of a
lower-case hex string representation of the pubkey.
This adds a hack for compatibility up to HF18, then at HF18 switches to
sorting by direct binary pubkey values.
If we're skipping it we don't care about it being missing.
Without this we get a bunch of warnings whenever an unfilled awaiting
contributions node has not yet submitted proofs or is abandoned (which
is usually the case on testnet, and sometimes on mainnet).
Sending a bogus sn.onion_req with a "ping" argument was a gross hack
that was needed for a backwards mid-hf update a long time ago; this
finally replaces it to a proper endpoint (starting at HF18).
- Do the json parsing as part of the payload parsing rather than
allocating a string and then making the caller do it (there's no case
where the caller *doesn't* want to do it).
- Modernize code to use structured bindings, allowing both cleaner code
and reduction in the number of moves/copies.
Since pings are 30s now, the ping spam is quite prevalent in the logs,
and unnecessary. (You can always do oxend status to find out when the
last ping was).
This commit changes ping reporting to work as follows:
- the first ping we get after startup or after a failed ping gets logged
at info level.
- subsequent successful pings get info-logged once/hour, including the
number of sequential successful pings we've done.
- otherwise the ping success message is a debug log statement.
This replaces the Monero crypto implementation with a backwards
compatible libsodium implementation. In particular, this replaces the
signature generation's random value with a deterministic value
H(H(a) || A || M)
(reduced and clamped). Since this deterministic value is perfectly good
as a "random" value, this avoids needing a RNG for generation, getting
us something closer (though still not) standard Ed25519 sigs.
An const lvalue reference is not something to be stored lightly, and can
easily break (as it did here). Fix it by accepting a value instead,
i.e. by making the code conform to the class API and not making the
class API confirm to the caller code.
The bootstrapping code was added because, long ago, oxend didn't have
ed/x keys and ip addresses after a restart, so on a SN restart it could
take an hour before we had a full view of the network.
This isn't the case anymore: ed/x/ip/etc. fields are persistent, so the
bootstrap code here is really only necessary for a fresh service node.
This commit thus adds a heuristic to only go to the bootstrap node if
our first snode list from oxend is missing data for more than 3% of the
service nodes; otherwise we just trust our local oxend result so that we
should, on an up-to-date service node, almost never need to contact the
bootstraps.
This also tweaks when we update local swarm data when bootstrapping so
that we recognize ourself as being active right away; the change to
pushed block notifications broke this by adding a delay to the next
arriving block (I think the old version didn't have this issue because
it hammered oxend once/second and so there would have only been a 1s
delay after bootstrap until the next rpc request).
Some API improvements:
- When we need to copy a shared_ptr in a function, taking it by
`const shared_ptr&` forces an extra atomic increment (and then
decrement at the call site). Change these to plain `shared_ptr` so
that the caller can decide whether they want to move (avoiding any
increment/decrement) or copy.
- When we *don't* need the shared_ptr container at all pass by reference
to the contained value instead because this pushes the responsibility
that the pointer not be null back to the caller.
Rather than sending "Host: service node" or "Host: service-node" we now
send "Host: whatever.snode" or "Host: service-node.snode" if we don't
have the ed25519 key yet.
Typically storage server output goes to systemd, which passes it off to
the journal; journalctl knows how to show (-a) ansi colors, and also
knows how to strip them when you don't provide -a.