Commit Graph

501 Commits

Author SHA1 Message Date
Jason Rhinelander bf4f62c58a Fix release suffix for stable 2020-10-11 23:00:36 -03:00
Jason Rhinelander 674fa682bb
Bump version (mainly wallet-related fixes) (#1312) 2020-10-12 10:43:29 +11:00
Jason Rhinelander 27aa2fb9bc Merge remote-tracking branch 'origin/stable' into dev 2020-10-03 23:35:37 -03:00
Jason Rhinelander f6c3adfb8e Small tweaks to build system
- make tagged and stable branch builds not add git tag to the tar.xz
  filename
- copy apt-get tweaks (to make it less noisy) from deb branches
- do a faster shallow submodule clone
- remove exclusion for removed is_hdd test
- remove deb_builder (deb building drone code is in its own branches)
- fix upload dir for a tagged build
2020-10-03 23:24:08 -03:00
Jason Rhinelander 9ae405c06c Merge commit '61d6564bc' into dev 2020-10-01 21:27:38 -03:00
Jason Rhinelander 61d6564bc3 Remove -dev suffix for stable branch 2020-10-01 21:21:37 -03:00
Jason Rhinelander 915e6109f6
Bump version to 8.1.0 and set HF16/17 fork times (#1295) 2020-10-01 11:36:25 +10:00
Jason Rhinelander a0bfda8e25 Bump version with testnet fixes 2020-09-29 20:26:52 -03:00
Jason Rhinelander 9eb854dedb
Drone: don't build debug tools in static builds (#1281)
The strip_binaries target was depending on all binaries, including
debug utilities, and so the static builds would end up building and
including them.

This makes strip_binaries not strip or depend on EXCLUDE_FROM_ALL
targets (or targets inside EXCLUDE_FROM_ALL directories) to prevent
this.  (A separate strip_binaries_all target is set up in case someone
builds them and wants to strip them as well).
2020-09-26 12:59:34 +10:00
Jason Rhinelander 23cecefe6f Merge remote-tracking branch 'origin/master' into master-to-dev 2020-09-21 19:09:14 -03:00
Jason Rhinelander b3f3de135d Bump dev version to 8.0.0
(For anyone watching at home: 8.0.x is our testnet version, the first
release meant for mainnet will be 8.1.0).
2020-09-18 19:21:48 -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 7cd8431982 Use cmake variable for enabling PIC
With the current approach -fPIC wasn't getting used when building
external libraries.  I tried moving add_subdirectory(external) down
below where we set flags, but that results in a slew or warning because
it *also* turn on a bunch of warnings that aren't safe in the various
external code.
2020-08-07 17:14:02 -03:00
Jason Rhinelander dc9101d457 Set ZMQ_STATIC definition on the target rather than globally 2020-07-02 12:55:28 -03:00
Jason Rhinelander 718a9496fb Replace boost chrono & posix_time with stl chrono 2020-07-02 12:52:13 -03:00
Jason Rhinelander 37a341ff6b Remove boost regex dependencies
All boost::regex use is now replaced with std::regex.
2020-07-02 12:52:13 -03:00
Jason Rhinelander d69b2c2e7b Remove mapbox-variant submodule check
lokimq no longer includes/uses it.
2020-07-02 12:52:13 -03:00
Jason Rhinelander 3191515e87 Only warn about not finding systemd on linux 2020-07-02 12:52:12 -03:00
Jason Rhinelander 2208432604 Set epee include dir via epee target instead of globally 2020-07-02 12:52:12 -03:00
Jason Rhinelander 42bd5f644b cmake simplifications
Remove some (already fixed) workarounds and logic that only applies to
compiler versions we left behind.
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
Jason Rhinelander 1f6bb56764
Remove -Ofast, use cmake defaults for release/debug (#1180)
-Ofast turns on -ffast-math, which allows gcc to do IEEE-violating FP
math optimizations.  The consequence of this is that it means a Release
build and a Debug build produce *different* difficulty values.  (It may
also have contributed to difficulty value divergence).

Turn it off because we are not Gentoo.

There is actually little point of setting CMAKE_CXX_FLAGS_RELEASE at all
here: adding `-DNDEBUG` is already the default for a cmake release
build, and cmake similarly has a release build default optimization
level (which I think is `-O3` -- which is already what we're doing with
`-Ofast` on Linux, except that `-Ofast` turns on unsafe stuff on top of
`-O3`).

For Debug build, this removes -Og and lets cmake use its default (-O0),
which is usually better when developing: lack of optimization means
faster binaries, are easier to trace.  The downside is enormous binaries
(~250MB), but that seems at least manageable for a debug build.
2020-06-22 15:33:23 +10:00
Jason Rhinelander 415027c6cd create_archive target: add targets to archive the bin/ build dir
From a cmake build dir (`make` used for simple example; can also be
something else, such as ninja):

    make create_tarxz
    make create_zip

creater a loki-<OS>[-arch]-x.y.z[-dev]-<GITHASH>.tar.xz or .zip.

    make create_archive

decides what to do based on the build type: creates a .zip for a windows
build, a tar.xz for anything else.  (We have been distributing the macOS
binaries as a .zip but that seems unnecessary: I tested on our dev mac
and a .tar.xz offers exactly the same UX as a .zip, but is noticeably
smaller).

From the top-level makefile there is also a new `make
release-full-static-archive` that does a full static build (include all
deps) and builds the archive.
2020-06-15 12:49:33 -03:00
Jason Rhinelander 70b9fed4fd Static builds: make usable binaries from cmake
This adds a static dependency script for libraries like boost, unbound,
etc. to cmake, invokable with:

    cmake .. -DBUILD_STATIC_DEPS=ON

which downloads and builds static versions of all our required
dependencies (boost, unbound, openssl, ncurses, etc.).  It also implies
-DSTATIC=ON to build other vendored deps (like miniupnpc, lokimq) as
static as well.

Unlike the contrib/depends system, this is easier to maintain (one
script using nicer cmake with functions instead of raw Makefile
spaghetti code), and isn't concerned with reproducible builds -- this
doesn't rebuild the compiler, for instance.  It also works with the
existing build system so that it is simply another way to invoke the
cmake build scripts but doesn't require any external tooling.

This works on Linux, Mac, and Windows.

Some random comments on this commit (for preserving history):

- Don't use target_link_libraries on imported targets.  Newer cmake is
fine with it, but Bionic's cmake doesn't like it but seems okay with
setting the properties directly.

- This rebuilds libzmq and libsodium, even though there is some
provision already within loki-core to do so: however, the existing
embedded libzmq fails with the static deps because it uses libzmq's
cmake build script, which relies on pkg-config to find libsodium which
ends up finding the system one (or not finding any), rather than the one
we build with DownloadLibSodium.  Since both libsodium and libzmq are
faily simple builds it seemed easiest to just add them to the cmake
static build rather than trying to shoehorn the current code into the
static build script.

- Half of the protobuf build system ignores CC/CXX just because Google,
and there's no documentation anywhere except for a random closed bug
report about needing to set these other variables (CC_FOR_BUILD,
CXX_FOR_BUILD) instead, but you need to.  Thanks Google.

- The boost build is set to output very little because even the minimum
-d1 output level spams ~15k lines of output just for the headers it
installs.
2020-06-15 12:49:33 -03:00
Jason Rhinelander da400f6d66 Rewrite translation file generation using cmake
This makes three big changes to how translation files are generated:

- use Qt5 cmake built-in commands to do the translations rather than
calling lrelease directly.  lrelease is often not in the path, while Qt5
cmake knows how to find and invoke it.

- Slam the resulting files into a C++ file using a cmake script rather
than needing to compile a .c file to generate C++ file.  This is
simpler, but more importantly avoids the mess needed when cross
compiling of having to import a cmake script from an external native
build.

- In the actual generated files, use an unordered_map rather than a
massive list of static variable pointers.
2020-06-15 12:49:33 -03:00
Jason Rhinelander 1c1a7e6f84 Remove cruft 2020-06-15 12:49:33 -03:00
Jason Rhinelander 98d1cab7ed Fix invalid cmake build type release -> Release
Lower-case "release" is not a valid cmake build type (it's "Release"),
so fix it.
2020-06-14 23:43:35 -03:00
Jason Rhinelander 1026ff680b Set up LTO properly
CMake 3.9+ has generic LTO enabling code, switch to it.

Update required cmake version to 3.10 (3.9 is probably sufficient, but
3.10 is bionic's version that we're actually testing).
2020-06-14 23:16:04 -03:00
Jason Rhinelander 630f346dba Set C++14 compilation mode properly
CMake has standard interfaces for this; hacking it into CXX_FLAGS is
just gross.
2020-06-14 22:18:50 -03:00
Jason Rhinelander ac29b79cd9 Do not try to feature test static_assert
static_assert is required both by C++11 and C11; if we don't have a
standard compliant compiler then compilation should fail, not be hacked
like this.

The C++ version of this definition is particularly preposterous; the C
version is probably just covering up that the C code forget to include
the `<assert.h>` header where the `static_assert` macro is defined.
2020-06-14 22:18:22 -03:00
Jason Rhinelander 8cff7c1664 Enable ccache by default
It can still be explicitly disabled with

    -DCMAKE_CXX_COMPILER_LAUNCHER= -DCMAKE_C_COMPILER_LAUNCHER=

if someone doesn't want it for some reason.
2020-06-14 22:10:38 -03:00
Jason Rhinelander f4e9ea7d40 Remove unbound submodule
There's really no reason to submodule it - we work with pretty much any
libunbound version, and it's a very commonly available library
(comparable to sqlite3 or boost, which we don't submodule).

This removes the submodule and switches it to a hard dependency.
2020-06-11 15:02:21 -03:00
Jason Rhinelander a9171c687f Remove -Wundef from compilation flags
This triggers a pile of false positives from gtest and mapbox variant.
In the case of gtest, these were being hidden by including gtest as a
system include, which was simply disgusting.
2020-06-09 23:06:54 -03:00
Jason Rhinelander 5954cb8234 Update and submodule gtest
The gtest version bundled inside tests/ is ancient (7 years old) and
doesn't build properly for some compilers.

Replace it with a current gtest submodule in external/.
2020-06-09 23:06:54 -03:00
Jason Rhinelander 9255d1080a Don't use external project for no reason
Using an external project to build a subdirectory is gross, and moreover
it breaks if you are trying to use a custom compiler and uses the wrong
one (or just fails if a `c++` binary doesn't exist).

Since the builds appear to run just fine without this, just include it
via add_subdirectory instead.
2020-06-09 23:06:54 -03:00
Jason Rhinelander e2ef747a15 Make false positive logical-op warning non-fatal
A lokimq header has a range comparison that can trigger a tautological
warning under xenial gcc; make it just a warning even with -Werror is
turned on.
2020-05-27 15:06:06 -03:00
Doyle 1a63c6bb4e Merge commit '4e2b139e7252fc4f72b63ea475e4611153f9b339' into MergeUpstream3 2020-05-25 14:26:32 +10:00
Doyle cd5b752584 Merge commit '353debe119c862c310aea4a50f9ace1c6afed2a1' into MergeUpstream3 2020-05-22 11:37:32 +10:00
Doyle 15fd7f8200 Merge branch 'dev' into MergeUpstream3 2020-05-20 14:59:12 +10:00
Jason Rhinelander b1cad5ced9 Simplify readline linking
Link readline directly into epee; having a separate epee_readline
library is not saving anything since we have it widely linked anyway.
Conditionally linking it to epee simplifies a bit of CMake code.

Also simplify how epee detects cmake to just look for a `readline`
target, which we now only set up if we find readline in the top-level
CMakeLists.txt
2020-05-20 00:47:38 -03:00
Doyle 184183f309 Merge branch 'dev' into MergeUpstream2 2020-05-18 12:58:59 +10:00
Doyle 30f4255689 Fix master merge assuming wrpc, vm and new versioning style 2020-05-15 14:06:07 +10:00
Jason Rhinelander d3a8baf9e7 Back out systemd linking to top-level CMakeLists
systemd notifies on startup really belong in daemon, not core, so this
paves the way for easily moving the calls there.
2020-05-11 18:44:45 -03:00
Jason Rhinelander 492d900693 Fix cmake policy warnings
The policy needs to be set before the `link_dep_libs` function (it was
before when it was in `external`, but this started generating warnings
again when I moved it from there to the top level CMakeLists.txt).
2020-05-11 18:44:45 -03:00
Doyle 0bcd895d7a Merge branch 'dev' into MergeUpstream2 2020-05-06 14:06:30 +10:00
Jason Rhinelander c50d2e93dc Add a LOKI_RELEASE_SUFFIX for adding "-dev" to dev branch builds
This will require a one-time change when we merge to master (to delete
the `-dev`) but after that it should just sit there without needing any
modifications on `master` or `dev`.  (And letting it be specified via
cmake arguments will let me slightly simplify the debs which currently
have to add a vaguely similar patch to get the debian version into the
version string).
2020-05-03 22:20:49 -03:00
Jason Rhinelander db5c053057 Move version into top-level CMakeLists.txt
CMake already provides variables to handle the version major/minor/patch
if we give it the dotted version in the `project()` command.  Using it
significantly reduces the amount of macro stuff we have to do in
version.cpp.in, and it seems a little nicer to have it defined in the
project top level rather than buried in a needs-to-beprocessed .cpp
file.

This moves the release codename there, too, so that it stays being
defined in essentially the same place as the version.

This change here requires some minor tweaking of the version generation
code to do it in two steps (when we have git): the first
(`src/version.cpp.in` -> `build/version.cpp.in`) replaces all the main
version variables during cmake configuration, the second
(`build/version.cpp.in` -> `build/version.cpp`) then replaces the
VERSIONTAG at build time.  (Before this commit, there was only version
tag replacement that only happened at build time).

Also bumps up the version here (since I'm moving it anyway) to match
master's 7.1.8.
2020-05-03 22:19:51 -03:00
Doyle 9e359f27e9 Merge commit '441f318180c402057df3eda278d3df130c31a3f1' into MergeUpstream2 2020-04-21 13:21:27 +10:00
Doyle 5f781e66ca Revert Boost_NO_BOOST_CMAKE, set rpc version 3.4, specify debug utils as option 2020-04-13 11:24:13 +10:00
Doyle 68c0b57c83 Move debug utilities cmake build message to correct CMakeList.txt 2020-04-09 16:37:47 +10:00