Commit graph

333 commits

Author SHA1 Message Date
Sean Darcy 866691d9d8 Batching of service node rewards
This updates the coinbase transactions to reward service nodes
periodically rather than every block. If you recieve a service node
reward this reward will be delayed x blocks, if you receive another
reward to the same wallet before those blocks have been completed it
will be added to your total and all will be paid out after those x
blocks has passed.

For example if our batching interval is 2 blocks:

Block 1 - Address A receives reward of 10 oxen - added to batch
Block 2 - Address A receives reward of 10 oxen - added to batch
Block 3 - Address A is paid out 20 oxen.

Batching accumulates a small reward for all nodes every block

The batching of service node rewards allows us to drip feed rewards
to service nodes. Rather than accruing each service node 16.5 oxen every
time they are pulse block leader we now reward every node the 16.5 /
num_service_nodes every block and pay each wallet the full amount that
has been accrued after a period of time (Likely 3.5 days).

To spread each payment evenly we now pay the rewards based on the
address of the recipient. This modulus of their address determines which
block the address should be paid and by setting the interval to our
service_node_batching interval we can guarantee they will be paid out
regularly and evenly distribute the payments for all wallets over this
2022-04-29 09:51:14 +10:00
Jason Rhinelander 5f1bd2f1e4 Drop integration test code.
This code is bitrotting, doesn't compile, and isn't being maintained
anymore.

The integration test suite was an interesting idea, in early Loki days,
but is no longer being maintained and is quite cumbersome to run (for
instance, it is not possible to run it via CI because it depends on
xterm to actually run).  The code to actually run it (in doy-lee's
loki-integration-testing repository) is also a large burden of "janky"
code that isn't worth maintaining.

Remove this from the code; if someone wants to pick it back up in the
future reverting this commit shouldn't be too difficult (though I'd
suggest that a much better approach to integration testing would be to
run different daemons/wallets via rpc commands, as the network-tests do,
rather than trying to feed stdin and parse stdout from running
individual oxends/wallets).
2021-08-19 16:42:15 -03:00
Jason Rhinelander 7b00cb251b Add snode revision soft forks & drop hard fork voting code
Snode revisions are a secondary version that let us put out a mandatory
update for snodes that isn't a hardfork (and so isn't mandatory for
wallets/exchanges/etc.).

The main point of this is to let us make a 9.2.0 release that includes
new mandatory minimums of future versions of storage server (2.2.0) and
lokinet (0.9.4) to bring upgrades to the network.

This slightly changes the HF7 blocks to 0 (instead of 1) because,
apparently, we weren't properly checking the HF value of the
pre-first-hf genesis block at all before.  (In practice this changes
nothing because genesis blocks are v7 anyway).

This also changes (slightly) how we check for hard forks: now if we skip
some hard forks then we still want to know the height when a hard fork
triggers.  For example, if the hf tables contains {7,14} then we still
need to know that the HF14 block height also is the height that
activates HF9, 10, etc.
2021-06-19 15:13:57 -03:00
Jason Rhinelander bbb8bdb1af Add lokinet reachability to quorum testing
It works just like storage server testing.

Renames the report_peer_storage_server_status to report_peer_status, and
repurposes the code to handle both SS and lokinet.

This *doesn't* need a HF by design because the reason bit field was
deliberately designed so that we can add reason fields (older clients
will just ignore unknown bits).
2021-06-10 12:13:33 -03:00
Jason Rhinelander ce9d0a9c1e Storage server RPC improvements
Improves the oxend<->storage server communications protocol:

- pass storage server HTTPS port as part of the storage server ping
(which already carries the also-required OMQ port) rather than needing
to provide it when starting up oxend.  --storage-server-port is now
obsolete (and ignored, if specified).
- Fix up the internal API to use `storage_https_port` and
`storage_omq_port` rather than `storage_port` and `storage_lmq_port`.
- Redo and the SS ping RPC endpoint so that it is less verbose and more
closely matches the lokinet endpoint; instead of:

    { "version_major": 2, "version_minor": 0, "version_patch": 9, "storage_lmq_port": 22222 }

we now expect:

    { "version": [2,0,9], "https_port": 11111, "omq_port": 22222 }

- Tweaks the (not-yet-released) SS proof key names: "s"->"shp" and "slp"->"sop"
2021-04-08 13:42:33 -03:00
Jason Rhinelander 2f5ec0e1e6 lmq -> omq internal rename
More rebrand updates to rename lmq (lokimq) internals with omq (oxenmq).
2021-04-08 13:38:51 -03:00
Jason Rhinelander 10a19d98de Avoid calling get_net_config() too early
m_nettype won't be set properly during construction so we can't call
get_net_config() in the constructor arguments here; set a reasonable
value and then update during actual initialization instead.
2021-03-25 12:44:30 -03:00
Jason Rhinelander 2fb0dbcaa3 Tweak uptime proof times; reduce times for testnet
This makes uptime proof times network-dependent, and tweaks them a bit.
Also converts the times to type-safe std::chrono types rather than
macros.

Mainnet/testnet/devnet:

- Send the first proof 30s after startup rather than waiting 2 minutes.
- Check for whether we need to send a proof every 30s rather than every
5mins.

Mainnet:

Other times unchanged.

Testnet/devnet:

- Send proofs every 10min instead of 1h, and consider nodes to be down
after 21m instead of 2h5m.

Fakechain:

- Send 5s after startup, check every 5s, and send every 1min.
- Expiry after 2min5s

Also remove the cmake debug option for short proofs since the fakechain
changes above basically incorporate what it did.
2021-03-25 11:46:23 -03:00
Sean Darcy b720e8ace6 Serialize the uptime proof using btencoding 2021-02-09 11:54:00 +11:00
Sean Darcy c0de851d1d Added versions for SS and lokinet to be saved to core, generate_uptime_proof adds them to the proof 2021-02-09 11:52:31 +11:00
Jason Rhinelander 466a1317d2 Rename lokimq -> oxenmq 2021-01-14 19:35:00 -04:00
Sean Darcy 851f9af707 lokinet revert 2021-01-04 15:21:21 +11:00
Sean Darcy 0396698ee7 initial loki -> oxen pass 2021-01-04 11:09:45 +11:00
Sean Darcy ed5b946c0a quorumnet message for timestamp requests
random sampling of service nodes, call timestamp lmq message

checks timestamp of 5 service nodes, if local time is 30 seconds different from 80% of the nodes tested then warn user

tracks external timesync status and timestamp participation of service nodes

clean up includes

new template struct for participation history, individual types for participation entry

refactor checking participation

update select_randomly, move the testing for variance overflow

version locks, bump to 8.1.5

explicit casting for mac & clang

note to remove after hard fork

timestamp debugging log messages

debugging messages for before timesync - before message sent

logging errord with compiling

print version and change add_command to add_request_command

log if statement test

std::to_string replaced with tools::view_guts for x25519 key

check if my sn is active before sending timestamp requests

logging the failures

checking if statement for success of message

more logging, if guards arn't passing

more logging, successfully tests if service node might be out of sync

more tests before we decide we are out of sync

logging output if sn isn't passing tests

if check_participation fails then disconnect

print timestamp status

remove saving variance from the participation history

reduce MIN_TIME_IN_S_BEFORE_VOTING

reset participation history on recommission

undo reduction in startup time

reduce log levels

Set hardfork time in testnet
2020-12-18 16:05:51 +11:00
Jason Rhinelander b627b3b4bb Move epee includes under "epee/..."
This ends epee's include pollution.
2020-10-24 12:46:27 -03:00
Jason Rhinelander 1dd98f3dae std::filesystem
Converts all use of boost::filesystem to std::filesystem.

For macos and potentially other exotic systems where std::filesystem
isn't available, we use ghc::filesystem instead (which is a drop-in
replacement for std::filesystem, unlike boost::filesystem).

This also greatly changes how we handle filenames internally by holding
them in filesystem::path objects as soon as possible (using
fs::u8path()), rather than strings, which avoids a ton of issues around
unicode filenames.  As a result this lets us drop the boost::locale
dependency on Windows along with a bunch of messy Windows ifdef code,
and avoids the need for doing gross boost locale codecvt calls.
2020-10-24 12:45:37 -03:00
Jason Rhinelander e496e502f2
LMQ: get config directory from core instead of arg parsing (#1284)
There are some cases where core modified the config folder that the
default lmq control socket would miss; this cleans it up to get the
config folder from core rather than trying to use core's command-line
argument.
2020-09-27 13:57:07 +10:00
Jason Rhinelander 928b4ac796 More efficient get-block-by-height lookups
Currently where we need to look up a block by height we do:

1. get block hash for the given height
2. look up block by hash

This hits the lmdb layer and does:

3. look up height from hash in hashes-to-height table
4. look up block from height in blocks table

which is pointless.  This commit adds a `get_block_by_height()` that
avoids the extra runaround, and converts code doing height lookups to
use the new method.
2020-09-18 20:25:48 -03:00
Doyle 31b9fbff91 Pulse: Record pulse participation and issue decommission 2020-09-18 13:50:05 -03:00
Doyle 9bec861f4d core: Remove recalc diff from core, we rescan on startup
We always rescan from 0 because of a difficulty bug, so instead just
move it to blockchain_import where you might occasionally want
fine-tuned access to it.
2020-09-18 13:50:05 -03:00
Jason Rhinelander feb8d5663a
Fix bl.* commands not being registered (#1237)
bl.* weren't being registered for non-service nodes.  This fixes it by
moving endpoint setup from quorumnet_new (SN-only) to a new
quorumnet_init that does endpoint setup (for both SNs and non-SNs).
2020-08-21 17:01:37 +10:00
Doyle 8bcb4276a0 Pulse: Pull handshake sending code out of quorumnet 2020-08-18 11:59:54 +10:00
Doyle 1c759c50fe Pulse: Remove wrapper function for send_block_template
- Don't need it when the function in quorumnet does so little work. The
added boilerplate of function pointers is more cost than its worth.
2020-08-18 11:59:54 +10:00
Doyle 55086cad8f Pulse: Convert to event based pulse loop
- Respond to pulse events by submitting to the LokiMQ thread job queue
instead of managing our own queue.
2020-08-18 11:59:53 +10:00
Doyle a62ff316e3 Pulse: Queue Block Gen code review
- Rename find_named_argument -> find_prefixed_value
- Update get_current_blockchain_height() comment to specify ability to lock
- Update memcmp(address1, address2) to address1 == address2
- Make create_next_miner_block_template call create_miner_block_template
- Update LMQ x25519 keys only when key has changed
- construct_miner_tx: Use C++17 features
- Pulse: Add log category "Pulse"
- Pulse: Check shutdown before blockchain height
- Pulse: Use get_human_readable_timespan
- Pulse: Switch to MINFO, enable with --log-level +pulse:DEBUG
- Pulse: Add height into context
- Pulse: Remove some default switch cases hiding compiler warnings
- SN: Update hardcoded '9' literals to network_version_9_service_nodes
- Core: Use using namespace std::literals
- Miner: Change num_blocks availability to debug
- RPC: Gate test rpc commands to != MAINNET
- Wallet: Store wallet before deinitialization instead of refresh
2020-08-18 11:59:53 +10:00
Doyle ba5f955f87 Pulse: Add relay signed pulse block template pulse round 2020-08-18 11:59:53 +10:00
Doyle 9ebebec7d2 Pulse: Fix most common bitset selection 2020-08-18 11:59:53 +10:00
Doyle b2f8a328b4 Pulse: Add more documentation 2020-08-18 11:59:53 +10:00
Doyle 2232ecb46b Pulse: Add main block gen/validator handshake synchronizing worker 2020-08-18 11:59:53 +10:00
Doyle f50e3ce898 Remove unused init_core_callback, inline lambdas 2020-08-18 11:59:53 +10:00
Doyle e40c7a0995 Use aliases for quorumnet function pointers 2020-08-18 11:59:53 +10:00
Doyle 5c2c35c0d6 Pulse: Make create block template have pulse/miner variants 2020-08-18 11:59:53 +10:00
Doyle a6e1f82f7a Pulse: Make active snodes info public, disambiguate next_block_template
- Make active snods info public for Pulse to query the list to allow
  Pulse quorums to be generated outside of the Service Node List.
2020-08-18 11:59:53 +10:00
Jason Rhinelander ef91df6af0 Rename stagenet to devnet 2020-08-17 02:54:43 -03:00
Jason Rhinelander 95fe5f4533 Cache get_coinbase_tx_sum-from-0 result
This caches the result of a get_coinbase_tx_sum to H-30 (if the last
request started from 0 and retrieved up to at least H-30).  This makes
get_coinbase_tx_sum calls to get the full chain values massively faster
for all but the first call.

The "first call" is kind of tricky, though, because it can take a couple
minutes, during which if we get multiple calls (e.g. from the block
explorer) we might get multiple threads trying to create the cache all
at once, and *each* of those takes minutes (and chew up an admin rpc
thread).  So this commit also blocks out other threads from getting a
cacheable result while the cache is being built; instead those calls get
a null optional back.

Once the cache is built, requests start returning pretty much instantly
(on my desktop system with the blockchain data cached in RAM I process
around 5k blocks per second).
2020-08-17 02:44:17 -03:00
Jason Rhinelander fb0aff57f6 Replace epee http client with curl-based client
In short: epee's http client is garbage, standard violating, and
unreliable.

This completely removes the epee http client support and replaces it
with cpr, a curl-based C++ wrapper.  rpc/http_client.h wraps cpr for RPC
requests specifically, but it is also usable directly.

This replacement has a number of advantages:

- requests are considerably more reliable.  The epee http client code
  assumes that a connection will be kept alive forever, and returns a
  failure if a connection is ever closed.  This results in some very
  annoying things: for example, preparing a transaction and then waiting
  a long tim before confirming it will usually result in an error
  communication with the daemon.  This is just terribly behaviour: the
  right thing to do on a connection failure is to resubmit the request.

- epee's http client is broken in lots of other ways: for example, it
  tries throwing SSL at the port to see if it is HTTPS, but this is
  protocol violating and just breaks (with a several second timeout) on
  anything that *isn't* epee http server (for example, when lokid is
  behind a proxying server).

- even when it isn't doing the above, the client breaks in other ways:
  for example, there is a comment (replaced in this PR) in the Trezor PR
  code that forces a connection close after every request because epee's
  http client doesn't do proper keep-alive request handling.

- it seems noticeably faster to me in practical use in this PR; both
  simple requests (for example, when running `lokid status`) and
  wallet<->daemon connections are faster, probably because of crappy
  code in epee.  (I think this is also related to the throw-ssl-at-it
  junk above: the epee client always generates an ssl certificate during
  static initialization because it might need one at some point).

- significantly reduces the amount of code we have to maintain.

- removes all the epee ssl option code: curl can handle all of that just
  fine.

- removes the epee socks proxy code; curl can handle that just fine.
  (And can do more: it also supports using HTTP/HTTPS proxies).

- When a cli wallet connection fails we know show why it failed (which
  now is an error message from curl), which could have all sorts of
  reasons like hostname resolution failure, bad ssl certificate, etc.
  Previously you just got a useless generic error that tells you
  nothing.

Other related changes in this PR:

- Drops the check-for-update and download-update code.  To the best of
my knowledge these have never been supported in loki-core and so it
didn't seem worth the trouble to convert them to use cpr for the
requests.

- Cleaned up node_rpc_proxy return values: there was an inconsistent mix
  of ways to return errors and how the returned strings were handled.
  Instead this cleans it up to return a pair<bool, val>, which (with
  C++17) can be transparently captured as:

    auto [success, val] = node.whatever(req);

  This drops the failure message string, but it was almost always set to
  something fairly useless (if we want to resurrect it we could easily
  change the first element to be a custom type with a bool operator for
  success, and a `.error` attribute containing some error string, but
  for the most part the current code wasn't doing much useful with the
  failure string).

- changed local detection (for automatic trusted daemon determination)
  to just look for localhost, and to not try to resolve anything.
  Trusting non-public IPs does not work well (e.g. with lokinet where
  all .loki addresses resolve to a local IP).

- ssl fingerprint option is removed; this isn't supported by curl
  (because it is essentially just duplicating what a custom cainfo
  bundle does)

- --daemon-ssl-allow-chained is removed; it wasn't a useful option (if
  you don't want chaining, don't specify a cainfo chain).

- --daemon-address is now a URL instead of just host:port.  (If you omit
  the protocol, http:// is prepended).

- --daemon-host and --daemon-port are now deprecated and produce a
  warning (in simplewallet) if used; the replacement is to use
  --daemon-address.

- --daemon-ssl is deprecated; specify --daemon-address=https://whatever
  instead.

- the above three are now hidden from --help

- reordered the wallet connection options to make more logical sense.
2020-08-07 17:14:03 -03:00
Jason Rhinelander 42a7e83c33 Replace epee http rpc server with uWebSockets
This replaces the NIH epee http server which does not work all that well
with an external C++ library called uWebSockets.  Fundamentally this
gives the following advantages:

- Much less code to maintain
- Just one thread for handling HTTP connections versus epee's pool of
threads
- Uses existing LokiMQ job server and existing thread pool for handling
the actual tasks; they are processed/scheduled in the same "rpc" or
"admin" queues as lokimq rpc calls.  One notable benefit is that "admin"
rpc commands get their own queue (and thus cannot be delayed by long rpc
commands).  Currently the lokimq threads and the http rpc thread pool
and the p2p thread pool and the job queue thread pool and the dns lookup
thread pool and... are *all* different thread pools; this is a step
towards consolidating them.
- Very little mutex contention (which has been a major problem with epee
RPC in the past): there is one mutex (inside uWebSockets) for putting
responses back into the thread managing the connection; everything
internally gets handled through (lock-free) lokimq inproc sockets.
- Faster RPC performance on average, and much better worst case
performance.  Epee's http interface seems to have some race condition
that ocassionally stalls a request (even a very simple one) for a dozen
or more seconds for no good reason.
- Long polling gets redone here to no longer need threads; instead we
just store the request and respond when the thread pool, or else in a
timer (that runs once/second) for timing out long polls.

---

The basic idea of how this works from a high level:

We launch a single thread to handle HTTP RPC requests and response data.
This uWebSockets thread is essentially running an event loop: it never
actually handles any logic; it only serves to shuttle data that arrives
in a request to some other thread, and then, at some later point, to
send some reply back to that waiting connection.  Everything is
asynchronous and non-blocking here: the basic uWebSockets event loop
just operates as things arrive, passes it off immediately, and goes back
to waiting for the next thing to arrive.

The basic flow is like this:

    0. uWS thread -- listens on localhost:22023
    1. uWS thread -- incoming request on localhost:22023
    2. uWS thread -- fires callback, which injects the task into the LokiMQ job queue
    3. LMQ main loop -- schedules it as an RPC job
    4. LMQ rpc thread -- Some LokiMQ thread runs it, gets the result
    5. LMQ rpc thread -- Result gets queued up for the uWS thread
    6. uWS thread -- takes the request and starts sending it
       (asynchronously) back to the requestor.

In more detail:

uWebSockets has registered has registered handlers for non-jsonrpc
requests (legacy JSON or binary).  If the port is restricted then admin
commands get mapped to a "Access denied" response handler, otherwise
public commands (and admin commands on an unrestricted port) go to the
rpc command handler.

POST requests to /json_rpc have their own handler; this is a little
different than the above because it has to parse the request before it
can determine whether it is allowed or not, but once this is done it
continues roughly the same as legacy/binary requests.

uWebSockets then listens on the given IP/port for new incoming requests,
and starts listening for requests in a thread (we own this thread).
When a request arrives, it fires the event handler for that request.
(This may happen multiple times, if the client is sending a bunch of
data in a POST request).  Once we have the full request, we then queue
the job in LokiMQ, putting it in the "rpc" or "admin" command
categories.  (The one practical different here is that "admin" is
configured to be allowed to start up its own thread if all other threads
are busy, while "rpc" commands are prioritized along with everything
else.)  LokiMQ then schedules this, along with native LokiMQ "rpc." or
"admin." requests.

When a LMQ worker thread becomes available, the RPC command gets called
in it and runs.  Whatever output it produces (or error message, if it
throws) then gets wrapped up in jsonrpc boilerplate (if necessary), and
delivered to the uWebSockets thread to be sent in reply to that request.

uWebSockets picks up the data and sends whatever it can without
blocking, then buffers whatever it couldn't send to be sent again in a
later event loop iteration once the requestor can accept more data.
(This part is outside lokid; we only have to give uWS the data and let
it worry about delivery).

---

PR specifics:

Things removed from this PR:

1. ssl settings; with this PR the HTTP RPC interface is plain-text.  The
previous default generated a self-signed certificate for the server on
startup and then the client accepted any certificate.  This is actually
*worse* than unencrypted because it is entirely MITM-readable and yet
might make people think that their RPC communication is encrypted, and
setting up actual certificates is difficult enough that I think most
people don't bother.

uWebSockets *does* support HTTPS, and we could glue the existing options
into it, but I'm not convinced it's worthwhile: it works much better to
put HTTPS in a front-end proxy holding the certificate that proxies
requests to the backend (which can then listen in restricted mode on
some localhost port).  One reason this is better is that it is much
easier to reload and/or restart such a front-end server, while
certificate updates with lokid require a full restart.  Another reason
is that you get an error page instead of a timeout if something is wrong
with the backend.  Finally we also save having to generate a temporary
certificate on *every* lokid invocation.

2. HTTP Digest authentication.  Digest authentication is obsolete (and
was already obsolete when it got added to Monero).  HTTP-Digest was
originally an attempt to provide a password authentication mechanism
that does not leak the password in transit, but still required that the
server know the password.  It only has marginal value against replay
attacks, and is made entirely obsolete by sending traffic over HTTPS
instead.  No client out there supports Digest but *not* Basic auth, and
so given the limited usefulness it seems pointless to support more than
Basic auth for HTTP RPC login.

What's worse is that epee's HTTP Digest authentication is a terrible
implementation: it uses boost::spirit -- a recursive descent parser
meant for building complex language grammars -- just to parse a single
HTTP header for Digest auth.  This is a big load of crap that should
never have been accepted upstream, and that we should get rid of (even
if we wanted to support Digest auth it takes less than 100 lines of code
to do it when *not* using a recursive descent parser).
2020-08-07 17:14:02 -03:00
Jason Rhinelander 54ca96b997 Fix warnings and unintended copies
- pessimizing move in wallet2 prevents copy ellision

- various for loops were creating copies (clang-10 now warns about
  this).  Mostly this is because they had the type wrong when looping
  through a map: the iterator type of a `map<K, V>` is `pair<const K,
  V>` not `pair<K, V>`.  Replaced them with C++17:

    for (const auto& [key, val] : var)

  which is so much nicer.

- cryptonote::core did not have a virtual destructor, but had virtual
  methods (causing both a warning, and likely a crash if we ever have
  something inheriting from it held in a unique_ptr<core>).

- core() constructor still had explicit even though it lost the single
  argument.

- test code class had a `final` destructor but wasn't marked final.  (It
  also has a billion superfluous `virtual` declarations but I left them
  in place because it's just test code).
2020-07-02 12:52:13 -03:00
Jason Rhinelander 4373f87d25 Remove useless method
parse_tx_from_blob is only ever called from one place and does
absolutely nothing except call some other function which can just be
done directly.
2020-07-02 12:52:13 -03:00
Jason Rhinelander e02545ca4b boost->std: mutex, locks; C++17 lock vars
Changes all boost mutexes, locks, and condition_variables to their stl
equivalents.

Changes all lock_guard/unique_lock/shared_lock to not specify the mutex
type (C++17), e.g.

    std::lock_guard foo{mutex};

instead of

    std::lock_guard<oh::um::what::mutex> foo{mutex};

Also changes some related boost::thread calls to std::thread, and some
related boost chrono calls to stl chrono.

boost::thread isn't changed here to std::thread because some of the
instances rely on some boost thread extensions.
2020-07-02 12:52:12 -03:00
Jason Rhinelander 83dd656e74 C++17
Switch loki dev branch to C++17 compilation, and update the code with
various C++17 niceties.

- stop including the (deprecated) lokimq/string_view.h header and
instead switch everything to use std::string_view and `""sv` instead of
`""_sv`.

- std::string_view is much nicer than epee::span, so updated various
loki-specific code to use it instead.

- made epee "portable storage" serialization accept a std::string_view
instead of const lvalue std::string so that we can avoid copying.

- switched from mapbox::variant to std::variant

- use `auto [a, b] = whatever()` instead of `T1 a; T2 b; std::tie(a, b)
= whatever()` in a couple places (in the wallet code).

- switch to std::lock(...) instead of boost::lock(...) for simultaneous
lock acquisition.  boost::lock() won't compile in C++17 mode when given
locks of different types.

- removed various pre-C++17 workarounds, e.g. for fold expressions,
unused argument attributes, and byte-spannable object detection.

- class template deduction means lock types no longer have to specify
the mutex, so `std::unique_lock<std::mutex> lock{mutex}` can become
`std::unique_lock lock{mutex}`.  This will make switching any mutex
types (e.g. from boost to std mutexes) far easier as you just have to
update the type in the header and everything should work.  This also
makes the tools::unique_lock and tools::shared_lock methods redundant
(which were a sort of poor-mans-pre-C++17 way to eliminate the
redundancy) so they are now gone and replaced with direct unique_lock or
shared_lock constructions.

- Redid the LNS validation using a string_view; instead of using raw
char pointers the code now uses a string view and chops off parts of the
view as it validates.  So, for instance, it starts with "abcd.loki",
validates the ".loki" and chops the view to "abcd", then validates the
first character and chops to "bcd", validates the last and chops to
"bc", then can just check everything remaining for is-valid-middle-char.

- LNS validation gained a couple minor validation checks in the process:
  - slightly tightened the requirement on lokinet addresses to require
    that the last character of the mapped address is 'y' or 'o' (the
    last base32z char holds only one significant bit).
  - In parse_owner_to_generic_owner made sure that the owner value has
    the correct size (otherwise we could up end not filling or
    overfilling the pubkey buffer).

- Replaced base32z/base64/hex conversions with lokimq's versions which
have a nicer interface, are better optimized, and don't depend on epee.
2020-07-02 12:52:12 -03:00
Doyle 469e6bc583 output_blacklist: Remove redundant return, report exception 2020-06-02 15:50:27 +10:00
Doyle d703d14d56 Merge commit 'c038cc8b791ffb4bcd5f13e47de1ea98815059fe' into MergeUpstream3 2020-05-28 12:23:19 +10:00
Doyle d84679e269 Merge commit '5e492c4cbcf966d8e73601358d35d70eb75bb4ca' into MergeUpstream3 2020-05-27 17:17:46 +10:00
Doyle 2e42202e94 Merge commit 'dcff02e4c3b1214143b19685361c3c6cffa62be7' into MergeUpstream3 2020-05-26 15:15:25 +10:00
Doyle 12076c3f3e Merge commit '8cc7d5b6c0c611dd03eba21c9cc7a9a043fa7b04' into MergeUpstream3 2020-05-25 16:08:05 +10:00
Doyle 0f818c929b Merge commit 'f253bf3' into MergeUpstream3 2020-05-25 15:17:47 +10:00
Jason Rhinelander a40bdd15b9 Don't generate SN pubkey when not a SN
We still generate the ed/x keys, but don't need the Monero key for
anything.
2020-05-11 18:45:15 -03:00
Jason Rhinelander 0e3f173c7f RPC overhaul
High-level details:

This redesigns the RPC layer to make it much easier to work with,
decouples it from an embedded HTTP server, and gets the vast majority of
the RPC serialization and dispatch code out of a very commonly included
header.

There is unfortunately rather a lot of interconnected code here that
cannot be easily separated out into separate commits.  The full details
of what happens here are as follows:

Major details:
- All of the RPC code is now in a `cryptonote::rpc` namespace; this
  renames quite a bit to be less verbose: e.g. CORE_RPC_STATUS_OK
  becomes `rpc::STATUS_OK`, and `cryptonote::COMMAND_RPC_SOME_LONG_NAME`
  becomes `rpc::SOME_LONG_NAME` (or just SOME_LONG_NAME for code already
  working in the `rpc` namespace).
- `core_rpc_server` is now completely decoupled from providing any
  request protocol: it is now *just* the core RPC call handler.
- The HTTP RPC interface now lives in a new rpc/http_server.h; this code
  handles listening for HTTP requests and dispatching them to
  core_rpc_server, then sending the results back to the caller.
- There is similarly a rpc/lmq_server.h for LMQ RPC code; more details
  on this (and other LMQ specifics) below.
- RPC implementing code now returns the response object and throws when
  things go wrong which simplifies much of the rpc error handling.  They
  can throw anything; generic exceptions get logged and a generic
  "internal error" message gets returned to the caller, but there is
  also an `rpc_error` class to return an error code and message used by
  some json-rpc commands.
- RPC implementing functions now overload `core_rpc_server::invoke`
  following the pattern:

    RPC_BLAH_BLAH::response core_rpc_server::invoke(RPC_BLAH_BLAH::request&& req, rpc_context context);

  This overloading makes the code vastly simpler: all instantiations are
  now done with a small amount of generic instantiation code in a single
  .cpp rather than needing to go to hell and back with a nest of epee
  macros in a core header.
- each RPC endpoint is now defined by the RPC types themselves,
  including its accessible names and permissions, in
  core_rpc_server_commands_defs.h:
  - every RPC structure now has a static `names()` function that returns
    the names by which the end point is accessible.  (The first one is
    the primary, the others are for deprecated aliases).
  - RPC command wrappers define their permissions and type by inheriting
    from special tag classes:
    - rpc::RPC_COMMAND is a basic, admin-only, JSON command, available
      via JSON RPC.  *All* JSON commands are now available via JSON RPC,
      instead of the previous mix of some being at /foo and others at
      /json_rpc.  (Ones that were previously at /foo are still there for
      backwards compatibility; see `rpc::LEGACY` below).
    - rpc::PUBLIC specifies that the command should be available via a
      restricted RPC connection.
    - rpc::BINARY specifies that the command is not JSON, but rather is
      accessible as /name and takes and returns values in the magic epee
      binary "portable storage" (lol) data format.
    - rpc::LEGACY specifies that the command should be available via the
      non-json-rpc interface at `/name` for backwards compatibility (in
      addition to the JSON-RPC interface).
- some epee serialization got unwrapped and de-templatized so that it
  can be moved into a .cpp file with just declarations in the .h.  (This
  makes a *huge* difference for core_rpc_server_commands_defs.h and for
  every compilation unit that includes it which previously had to
  compile all the serialization code and then throw all by one copy away
  at link time).  This required some new macros so as to not break a ton
  of places that will use the old way putting everything in the headers;
  The RPC code uses this as does a few other places; there are comments
  in contrib/epee/include/serialization/keyvalue_serialization.h as to
  how to use it.
- Detemplatized a bunch of epee/storages code.  Most of it should have
  have been using templates at all (because it can only ever be called
  with one type!), and now it isn't.  This broke some things that didn't
  properly compile because of missing headers or (in one case) a messed
  up circular dependency.
- Significantly simplified a bunch of over-templatized serialization
  code.
- All RPC serialization definitions is now out of
  core_rpc_server_commands_defs.h and into a single .cpp file
  (core_rpc_server_commands_defs.cpp).
- core RPC no longer uses the disgusting
  BEGIN_URI_MAP2/MAP_URI_BLAH_BLAH macros.  This was a terrible design
  that forced slamming tons of code into a common header that didn't
  need to be there.
- epee::struct_init is gone.  It was a horrible hack that instiated
  multiple templates just so the coder could be so lazy and write
  `some_type var;` instead of properly value initializing with
  `some_type var{};`.
- Removed a bunch of useless crap from epee.  In particular, forcing
  extra template instantiations all over the place in order to nest
  return objects inside JSON RPC values is no longer needed, as are a
  bunch of stuff related to the above de-macroization of the code.
- get_all_service_nodes, get_service_nodes, and get_n_service_nodes are
  now combined into a single `get_service_nodes` (with deprecated
  aliases for the others), which eliminates a fair amount of
  duplication.  The biggest obstacle here was getting the requested
  fields reference passed through: this is now done by a new ability to
  stash a context in the serialization object that can be retrieved by a
  sub-serialized type.

LMQ-specifics:

- The LokiMQ instance moves into `cryptonote::core` rather than being
  inside cryptonote_protocol.  Currently the instance is used both for
  qnet and rpc calls (and so needs to be in a common place), but I also
  intend future PRs to use the batching code for job processing
  (replacing the current threaded job queue).
- rpc/lmq_server.h handles the actual LMQ-request-to-core-RPC glue.
  Unlike http_server it isn't technically running the whole LMQ stack
  from here, but the parallel name with http_server seemed appropriate.
- All RPC endpoints are supported by LMQ under the same names as defined
  generically, but prefixed with `rpc.` for public commands and `admin.`
  for restricted ones.
- service node keys are now always available, even when not running in
  `--service-node` mode: this is because we want the x25519 key for
  being able to offer CURVE encryption for lmq RPC end-points, and
  because it doesn't hurt to have them available all the time.  In the
  RPC layer this is now called "get_service_keys" (with
  "get_service_node_key" as an alias) since they aren't strictly only
  for service nodes.  This also means code needs to check
  m_service_node, and not m_service_node_keys, to tell if it is running
  as a service node.  (This is also easier to notice because
  m_service_node_keys got renamed to `m_service_keys`).
- Added block and mempool monitoring LMQ RPC endpoints: `sub.block` and
  `sub.mempool` subscribes the connection for new block and new mempool
  TX notifications.  The latter can notify on just blink txes, or all
  new mempool txes (but only new ones -- txes dumped from a block don't
  trigger it).  The client gets pushed a [`notify.block`, `height`,
  `hash`] or [`notify.tx`, `txhash`, `blob`] message when something
  arrives.

Minor details:
- rpc::version_t is now a {major,minor} pair.  Forcing everyone to pack
  and unpack a uint32_t was gross.
- Changed some macros to constexprs (e.g. CORE_RPC_ERROR_CODE_...).
  (This immediately revealed a couple of bugs in the RPC code that was
  assigning CORE_RPC_ERROR_CODE_... to a string, and it worked because
  the macro allows implicit conversion to a char).
- De-templatizing useless templates in epee (i.e. a bunch of templated
  types that were never invoked with different types) revealed a painful
  circular dependency between epee and non-epee code for tor_address and
  i2p_address.  This crap is now handled in a suitably named
  `net/epee_network_address_hack.cpp` hack because it really isn't
  trivial to extricate this mess.
- Removed `epee/include/serialization/serialize_base.h`.  Amazingly the
  code somehow still all works perfectly with this previously vital
  header removed.
- Removed bitrotted, unused epee "crypted_storage" and
  "gzipped_inmemstorage" code.
- Replaced a bunch of epee::misc_utils::auto_scope_leave_caller with
  LOKI_DEFERs.  The epee version involves quite a bit more instantiation
  and is ugly as sin.  Also made the `loki::defer` class invokable for
  some edge cases that need calling before destruction in particular
  conditions.
- Moved the systemd code around; it makes much more sense to do the
  systemd started notification as in daemon.cpp as late as possible
  rather than in core (when we can still have startup failures, e.g. if
  the RPC layer can't start).
- Made the systemd short status string available in the get_info RPC
  (and no longer require building with systemd).
- during startup, print (only) the x25519 when not in SN mode, and
  continue to print all three when in SN mode.
- DRYed out some RPC implementation code (such as set_limit)
- Made wallet_rpc stop using a raw m_wallet pointer
2020-05-11 18:44:45 -03:00
Doyle 22d1b76fee Remove optional dependencies from constructor, no code actually uses it 2020-04-24 14:19:04 +10:00