Commit graph

539 commits

Author SHA1 Message Date
Doyle 632f6a6e83 Rebase fix, blink_lns -> blink, v15 and reserve types for protocol 2020-02-13 11:07:46 +11:00
Doyle d33c937dd4 Start move away from hooks, combine rescanning of lns and snl to one function
Call service_node_lists's block added hook function manually instead of
hooking the hook. There's a common operation between the 2 subsystems,
Loki Name Service and Service Node List, in which they generate state
based off incoming blocks from the blockchain.

Upon profiling, the slowest factor of this is retrieving the blocks from
the DB in batches of a 1000 rather than the processing of the blocks in
the subsystems. So flatten out the hierarchy so that we can retrieve the
batch and simultaneously process the blocks in both subsystems on the
same fetch request.

A complete removal of the hook system so we have more flexibility at the
callsite can be done in a later PR, to avoid too many unneccesary
changes in the LNS PR.
2020-02-13 11:07:46 +11:00
Doyle dc69d237e6 Add support for Loki Name Service on the backend 2020-02-13 11:07:46 +11:00
Doyle bb39a51b4b
Merge pull request #1021 from jagerman/blink-lock-fixes
Blink lock fixes
2020-01-20 10:47:24 +11:00
Jason Rhinelander 58a1494559 Add systemd notify & watchdog support (#1022)
This enables optional support for systemd notification which allows
lokid to be run via `Type=notify`, allowing it to better signal status
to systemd and enables systemd watchdog handling to restart if something
goes wrong.

Enabled here are:
- systemd watchdog ping every 10s
- systemd status update every 10s, so that `systemctl status loki-node`
  gives you a status line such as:

      Status: "Height: 450085, SN: active, proof: 15m12s, storage: 3m7s,  lokinet: 27s"
- initialization notification so that systemd can wait for
  and report on initialization status rather than just that the process
  has launched.
- shutdown notification

All of these require changing the service type to `Type=notify` in the
`[Service]` section of the systemd service file; enabling the watchdog
also requires adding a `WatchdogSec=5min` line in the `[Service]`
section.

The systemd support is optional and requires the libsystemd-dev package
to be built (and is probably not feasible at all for a static build).
2020-01-20 09:44:18 +11:00
Jason Rhinelander 0cd096fc22 Fix rare blink pool deadlock
cryptonote_protocol_handler calls `pool.get_blink(hash)` while already
holding a blink shared lock, which should have been
`pool.get_blink(hash, true)` to avoid `get_blink` trying to take its own
lock.

That double lock is undefined behaviour and can cause a deadlock on the
mutex, although it appears rare that it actually does.  If it does,
however, this eventually backs up into vote relaying during the idle
loop, which then stalls the idle loop so we stop sending out uptime
proofs (since that is also in the idle loop).

A simple fix here is to add the `true` argument, but on reconsideration
this extra argument to take or not take a lock is messy and error prone,
so this commit instead removes the second argument entirely and instead
documents which call must and must not hold a lock, getting rid of the
three methods (get_blink, has_blink, and add_existing_blink) that had
the `have_lock` argument.  This ends up having only a small impact on
calling code - the vast majority of callers already hold a lock, and the
few that don't are easily adjusted.
2020-01-18 22:29:26 -04:00
Jason Rhinelander 3c2eeb972b Remove pre-HF14 p2p vote relaying command 2020-01-18 12:12:29 -04:00
Doyle 04f9721c8f Long polling QOL, handle errors gracefully avoid lock contention
Handle errors better when long polling is disabled instead of endlessly
spamming logs.

Avoid lock contention when set_daemon is called. Instead of immediately
affecting the long polling thread (which could be engaging the mutex
until RPC timeout, meaning the program stalls for that duration), update
the address on the next iteration of the long polling thread.

Wallets handle daemons that disable long polling better by sleeping.
2020-01-10 13:07:37 +11:00
Doyle 6d71d2fd6e Rate limit long polling connections 2020-01-07 12:35:06 +11:00
Doyle 3009f8fff7 Add wallet long polling to wallet-cli 2020-01-07 12:35:06 +11:00
Jason Rhinelander b51fd0c5db --regtest fixes and mine n blocks ability
`--regtest` didn't work in some edge cases, this fixes various things:

- the genesis block wasn't accepted because it needed to be v7, not
  vMax
- reduce initial uptime proof delay to 5s in regtest mode
- add --regtest flag to the wallet so that it can talk to a daemon in
  --regtest mode.

This also adds two new mining options, available via rpc:

- slow_mining - this avoids the RandomX initialization.  It is much
  slower, but for regtest with fixed difficulty of 1 that is perfectly
  fine.
- `num_blocks` - instruct the miner to mine for the given number of
  blocks, then stop.  (This can overmine if mining with multiple
  threads at a low difficulty, but that's fine).
2019-12-26 12:29:05 -04:00
Jason Rhinelander eb0dfd64b0 Blink blockchain rollback fixes
Blockchain rollback conditions weren't being properly detected/handled.
2019-12-26 12:29:05 -04:00
Jason Rhinelander 1450c29795 Fix crash when receiving blocks for unknown quorum
This can occur when syncing if we get a blink tx before the blocks that
let us determine the quorum.  Just ignore it at this point; we'll pick
it up at the next once-per-minute sync run.
2019-12-26 12:29:05 -04:00
Jason Rhinelander f3fdcb1fbc Replace once_a_time_seconds; send proofs faster
This replaces the horrible, horrible, badly misused templated
once_a_time_seconds and once_a_time_milliseconds with a `periodic_task`
that works the same way but takes parameters as constructor arguments
instead of template parameters.

It also makes various small improvements:

- uses std::chrono::steady_clock instead of ifdef'ing platform dependent
  timer code.
- takes a std::chrono duration rather than a template integer and
  scaling parameter.
- timers can be reset to trigger on the next invocation, and this is
  thread-safe.
- timer intervals can be changed at run-time.

This all then gets used to reset the proof timer immediately upon
receiving a ping (initially or after expiring) from storage server and
lokinet so that we send proofs out faster.
2019-12-26 12:29:05 -04:00
Jason Rhinelander 19c562f800 Vote serialization compatibility fix (#984)
quorum_vote_t's were serialized as blob data, which is highly
non-portable (probably isn't the same on non-amd64 arches) and broke
between 5.x and 6.x because `signature` is aligned now (which changed
its offset and thus broke 5.x <-> 6.x vote transmission).

This adds a hack to write votes into a block of memory compatible with
AMD64 5.x nodes up until HF14, then switches to a new command that fully
serializes starting at the hard fork (after which we can remove the
backwards compatibility stuff added here).
2019-12-17 10:47:12 +10:00
Jason Rhinelander 9cd4615b35 Abstract assert + reinterpret_cast 2019-12-12 23:35:05 -04:00
Jason Rhinelander bbb72b5c17 Keep checkpoint votes over p2p
Checkpoint votes were only going over quorumnet, which was quite broken
as they need to go out universally: random nodes piece together the
individual checkpoints to create checkpoints on their own, and so need
to see all of the votes.  With the current code only service nodes that
participated in the specific quorum ever saw the checkpoint votes.

This commit returns checkpoint vote distribution to distribution over
p2p.

We could, in theory, do checkpoint vote collection over quorumnet and
then relay the set of votes as a pack to reduce p2p traffic a bit, but
this wouldn't be a huge optimization since we'd still have to distribute
all the votes over p2p at some point anyway, so leaving that as a future
optimization for now.

(Obligations votes, in contrast, don't need to be distributed at all --
if a vote results in a state change, the quorum members themselves can
produce and distribute the state change tx).
2019-12-10 16:29:17 -04:00
Jason Rhinelander b3d6150fa9 Store uptime proof data separately from states
This extracts uptime proof data entirely from service node states,
instead storing (some) proof data as its own first-class object in the
code and backed by the database.  We now persistently store:

- timestamp
- version
- ip & ports
- ed25519 pubkey

and update it every time a proof is received.  Upon restart, we load all
the proofs from the database, which means we no longer lose last proof
received times on restart, and always have the most recently received ip
and port information (rather than only having whatever it was in the
most recently stored state, which could be ~12 blocks ago).  It also
means we don't need to spam the network with proofs for up to half an
hour after a restart because we now know when we last sent (and
received) our own proof before restarting.

This separation required some restructuring: most notably changing
`state_t` to be constructed with a `service_node_list` pointer, which it
needs both directly and for BlockchainDB access.  Related to this is
also eliminating the separate BlockchainDB pointer stored in
service_node_list in favour of just accessing it via m_blockchain (which
now has a new `has_db()` method to detect when it has been initialized).
2019-12-09 22:26:38 -04:00
Doyle 9eb461f6b7 Don't query prune blockchain arg boost cast failure
Removing the prune blockchain arg from the command_line and trying to
query it causesd a boost any_cast failuree
2019-12-04 16:27:51 +11:00
Doyle 9471db15cc
Merge pull request #912 from Doy-lee/DisablePruning
Disable pruning in Loki, it is not supported yet
2019-12-04 15:36:19 +11:00
Doyle 1eb45e523e Build/core test fixes, incoporate staking changes from LNS
- Fix assert to use version_t::_count in service_node_list.cpp
- Incoporate staking changes from LNS which revamp construct tx to
  derive more of the parameters from hf_version and type. This removes
  extraneous parameters that can be derived elsewhere.

  Also delegate setting loki_construct_tx_params into wallet2 atleast,
  so that callers into the wallet logic, like rpc server, simplewallet
  don't need bend backwards to get the HF version whereas the wallet has
  dedicated functions for determining the HF.
2019-12-04 15:17:55 +11:00
Doyle 8df27d99b7
Merge pull request #935 from jagerman/blink-wallet-burn
Blink wallet burn
2019-11-29 13:51:00 +11:00
Doyle d04d692fdc
Check blockchain init failure before r is overwritten (#937) 2019-11-28 12:11:46 +11:00
Jason Rhinelander 7a34da8c09 Readd handle_incoming_txs & locking fixes
Rename handle_incoming_txs to handle_parsed_txs, and re-add a
handle_incoming_txs that does the parse+handle_parsed call with the
appropriate lock held for code that doesn't care about being able to
split it into two steps.

Clarifies the locking requirements with a comment in the code, and adds
an incoming tx lock over the blink receiving process in
cryptonote_protocol_handler.inl.

Also fixes a bug in the weight calculation happening because the
blobdata pointer was being invalidated when going through
the singular `handle_parsed_tx()`.
2019-11-27 14:36:41 -04:00
Jason Rhinelander 23fd73b97c Add tx pool blink replacement
This adds support for bumping conflicting transactions from the mempool
upon receipt of a blink tx if those conflicting txs are not themselves
blinks.

This commit chops the handle_incoming_txs effectively in half into a
parse_incoming_txs phase, followed by a handle_incoming_txs phase which
is needed so that we can first parse the txes then, assuming they parse
successfully, can flag them as blink txes if blink info was included
with them, so that the actual insertion becomes forcing.

There is a stub here for also allowing a rollback of the mutable part of
the chain; implementation of actually doing that rollback will follow in
another commit.
2019-11-27 14:36:38 -04:00
Jason Rhinelander e37ecd243a blink sync fixes
- actually include the blink hashes in the core sync data
- fix cleanup to delete heights in (0, immutable] instead of [0,
immutable); we want to keep 0 because it signifies the mempool, and we
only need blocks after immutable, not immutable itself.
- fixed NOTIFY_REQUEST_GET_TXS to handle mempool txes properly (it was
only searching the chain and ignored missed_txs, but missed_txs are ones
we need to look up in the mempool)
- Add a method to tx_pool (needed for the above) to grab multiple txes
by hash (essentially a multi-tx version of `get_transaction()`), and
change get_transaction() to use it with a single value.
- Added various debugging statements
- Added a bunch of comments to each condition of the preliminary blink
data check condition.
- Don't abort blink addition on a single signature failure: if there are
enough valid signatures we should still accept it.
- Check for blink signature approval when receiving blink signatures;
it's not enough to know that all were added successfully, we also have
to ask the blink tx if it is approved (which does additional checks on
subquorum counts) once we add them all.
2019-11-27 14:30:32 -04:00
Jason Rhinelander 24aadd8e59 Add blink HF version checks 2019-11-27 14:30:32 -04:00
Jason Rhinelander 5a81cd820e Add tx synchronization
This adds blink tx synchronization: when doing a periodic sync with
other nodes each node includes a map of {HEIGHT, HASH} pairs where
HEIGHT is a mined, post-immutable block height and HASH is an xor of all
the tx hashes mined into that block.

If upon receipt the node disagrees about what it thinks the HASH should
be, it can request a list of txes for one or more disagreeing heights,
for which it gets a list of tx hashes of all blink txes mined into that
block.

If it is then missing any of those TXes, this adds an ability to request
that the remote send TXes via the existing NOTIFY_NEW_TRANSACTIONS
mechanism, but with an added flag (so that these don't get relayed).

This originally was going to request the TXes via the existing
NOTIFY_REQUEST_GET_OBJECTS, which has a `txs` field, but unfortunately
any txs passed to it are completely ignored; it is *only* usable for
block synchronization.  As such I renamed it and removed the `txs` field
to make the responsibility/capability clearer.
2019-11-27 14:30:21 -04:00
Jason Rhinelander 6a886b69ea Generic burn fee checking + blink burn fee checking
This adds the ability for check_fee() to also check the burn amount.
This requires passing extra info through `add_tx()` (and the various
things that call it), so I took the:

    bool keeped_by_block, bool relayed, bool do_not_relay

argument triplet, moved it into a struct in tx_pool.h, then added the other fee
options there (along with some static factory functions for generating the
typical sets of option).

The majority of this commit is chasing that change through the codebase and
test suite.

This is used by blink but should also help LNS and other future burn
transactions to verify a burn amount simply when adding the transation to the
mempool.  It supports a fixed burn amount, a burn amount as a multiple of the
minimum tx fee, and also allows you to increase the minimum tx fee (so that,
for example, we could require blink txes to pay miners 250% of the usual
minimum (unimportant) priority tx fee.

- Removed a useless core::add_new_tx() overload that wasn't used anywhere.

Blink-specific changes:

(I'd normally separate these into a separate commit, but they got interwoven
fairly heavily with the above change).

- changed the way blink burning is specified so that we have three knobs for
fee adjustment (fixed burn fee; base fee multiple; and required miner tx fee).
The fixed amount is currently 0, base fee is 400%, and require miner tx fee is
simply 100% (i.e. no different than a normal transaction).  This is the same as
before this commit, but is changing how they are being specified in
cryptonote_config.h.

- blink tx fee, burn amount, and miner tx fee (if > 100%) now get checked
before signing a blink tx.  (These fee checks don't apply to anyone else --
when propagating over the network only the miner tx fee is checked).

- Added a couple of checks for blink quorums: 1) make sure they have reached
the blink hf; 2) make sure the submitted tx version conforms to the current hf
min/max tx version.

- print blink fee information in simplewallet's `fee` output

- add "typical" fee calculations in the `fee` output:

    [wallet T6SCwL (has locked stakes)]: fee
    Current fee is 0.000000850 loki per byte + 0.020000000 loki per output
    No backlog at priority 1
    No backlog at priority 2
    No backlog at priority 3
    No backlog at priority 4
    Current blink fee is 0.000004250 loki per byte + 0.100000000 loki per output
    Estimated typical small transaction fees: 0.042125000 (unimportant), 0.210625000 (normal), 1.053125000 (elevated), 5.265625000 (priority), 0.210625000 (blink)

where "small" here is the same tx size (2500 bytes + 2 outputs) used to
estimate backlogs.
2019-11-27 14:23:56 -04:00
Jason Rhinelander fb60191801 Review fixes
- set the proper promise
- reuse reference rather than repeating lookups
- fix unneeded mempool lock
2019-11-27 14:09:30 -04:00
Jason Rhinelander 442f2182d2 Blink synchronization
- Adds blink signature synchronization and storage through the regular
  p2p network
- Adds wallet support (though this is still currently buggy and needs
  additional fixes - it sees the tx when it arrives in the mempool but
  isn't properly updating when the blink tx gets mined.)
2019-11-27 14:09:28 -04:00
Jason Rhinelander ebb2bea452 Expose pool reference from core
There are a bunch trivial forwarding wrappers in cryptonote_core that
simply call the same method in the pool, and blink would require adding
several more.  Instead of all of these existing (and new) wrappers, just
directly expose the tx_pool reference so that anything with a `core`
reference can access and call to the mempool directly.
2019-11-27 14:08:57 -04:00
Jason Rhinelander 6e2d12e971 Remove unused, obsolete print_pool method
Pool printing is separately implemented in rpc_command_executor; this
method in tx_pool is both obsolete (missing some fields) and not called
anywhere.
2019-11-27 14:08:54 -04:00
Jason Rhinelander cf4d44fb10 Remove boost::value_initialized and BOOST_FOREACH
Neither of these have a place in modern C++11; boost::value_initialized
is entirely superseded by `Type var{};` which does value initialization
(or default construction if a default constructor is defined).  More
problematically, each `boost::value_initialized<T>` requires
instantiation of another wrapping templated type which is a pointless
price to pay the compiler in C++11 or newer.

Also removed is the AUTO_VAL_INIT macro (which is just a simple macro
around constructing a boost::value_initialized<T>).

BOOST_FOREACH is a similarly massive pile of code to implement
C++11-style for-each loops. (And bizarrely it *doesn't* appear to fall
back to C++ for-each loops even when under a C++11 compiler!)

This removes both entirely from the codebase.
2019-11-27 14:07:52 -04:00
Jason Rhinelander dd7a4104b5 Blink
This is the bulk of the work for blink.  There is two pieces yet to come
which will follow shortly, which are: the p2p communication of blink
transactions (which needs to be fully synchronized, not just shared,
unlike regular mempool txes); and an implementation of fee burning.

Blink approval, multi-quorum signing, cli wallet and node support for
submission denial are all implemented here.

This overhauls and fixes various parts of the SNNetwork interface to fix
some issues (particularly around non-SN communication with SNs, which
wasn't working).

There are also a few sundry FIXME's and TODO's of other minor details
that will follow shortly under cleanup/testing/etc.
2019-11-27 14:07:52 -04:00
Jason Rhinelander 5d28c9cf8d Switch service_node_keys to plain pointer instead of shared_ptr
The owning pointer is stashed in a unique_ptr so that it gets properly
destroyed; everything else gets a plain pointer to it.

(Ideally it would be std::optional instead, but that's not until C++17)
2019-11-27 14:07:52 -04:00
Jason Rhinelander 2dffb730b4 Expose accessor for service_node_list in core/blockchain
This adds direct access to the service node list via core/blockchain so
that it doesn't have to be passes around as reference in quite so many
places.
2019-11-27 14:07:52 -04:00
Jason Rhinelander dd230491db Uptime proof timer tweak + debug option
This tweaks uptime proofs to go out on the first timer tick in the
58.5-62.5 interval (rather than 60-65) which should result in proofs
usually being very close to the 60 minute mark.  (Currently a fair
percentage end up at the 65m mark because the timer fires just before
the 60m mark).

It also tweaks the first uptime proof to go out after 2 minutes instead
of 5 minutes, and uses separate constants
(UPTIME_PROOF_INITIAL_DELAY_SECONDS, UPTIME_PROOF_TIMER_SECONDS) for
times that were previously overloading the
UPTIME_PROOF_BUFFER_IN_SECONDS constant.

For debugging this also adds a cmake option LOKI_DEBUG_SHORT_PROOFS
that, when enabled, makes the whole proof cycle (sending and acceptance)
20x faster, which is very useful for local testnet debugging.
2019-11-27 14:07:52 -04:00
Jason Rhinelander a2727d5518 Blink WIP 2019-11-27 14:07:52 -04:00
Jason Rhinelander 2bc606fb89 Remove pointless check against already called 2019-11-27 14:07:52 -04:00
Jason Rhinelander 8a276b362f Store loki version as std::array<u16,3> everywhere
Currently we store it as various different things: 3 separate ints, 2
u16s, 3 separate u16s, and a vector of u16s.  This unifies all version
values to a `std::array<uint16_t,3>`.

- LOKI_VERSION_{MAJOR,MINOR,PATCH} are now just LOKI_VERSION
- The previous LOKI_VERSION (C-string of the version) is now renamed
  LOKI_VERSION_STR

A related change included here is that the restricted RPC now returns
the major version in the get_info rpc call instead of an empty string
(e.g. "5" instead of "").  There is almost certainly enough difference
in the RPC results to distinguish major versions already so this doesn't
seem like it actually leaks anything significant.
2019-11-27 14:07:52 -04:00
Jason Rhinelander 1b5234e6a6 Rename testing_quorum class to just quorum
testing_quorum is a bit of a misnomer: it only does testing when used
for an obligations quorum, but it is also used for checkpointing and
soon Blink.
2019-11-27 14:07:52 -04:00
Jason Rhinelander 57e64b7d1c Add quorumnet comms
This adds vote relaying via quorumnet.

- The main glue between existing code and quorumnet code is in
  cryptonote_protocol/quorumnet.{h,cpp}
- Uses function pointers assigned at initialization to call into the
  glue without making cn_core depend on p2p
- Adds ed25519 and quorumnet port to uptime proofs and serialization.
- Added a second uptime proof signature using the ed25519 key to that
  SNs are proving they actually have it (otherwise they could spoof
  someone else's pubkey).
- Adds quorumnet port, defaulting to zmq rpc port + 1.  quorumnet
  listens on the p2p IPv4 address (but broadcasts the `public_ip` to the
  network).
- Derives x25519 when received or deserialized.
- Converted service_info_info::version_t into a scoped enum (with the
  same underlying type).
- Added contribution_t::version_t scoped enum.  It was using
  service_info_info::version for a 0 value which seemed rather wrong.

Random small details:
- Renamed internal `arg_sn_bind_port` for consistency
- Moved default stagenet ports from 38153-38155 to 38056-38058, and add the default stagenet
  quorumnet port at 38059 (this keeps the range contiguous; otherwise the next stagenet default port
  would collide with the testnet p2p port).
2019-11-27 14:07:45 -04:00
Jason Rhinelander 34480c6f23 Merge branch 'pk25519-rpc-interfaces' into lokinet-integration 2019-11-26 21:47:07 -04:00
Jason Rhinelander b64097a47e Add lokinet ping rpc endpoint
This abstracts much of the storage server ping code to work for both
storage server and lokinet.
2019-11-26 18:49:37 -04:00
Jason Rhinelander f6bd747d94 Add optional get_n_sns RPC request; remove get_all_sn_pubkeys RPC
This allows a `"if_block_not_equal": "hash"` parameter to be given to
`get_n_service_nodes` which, if the given value matches the current
top block hash, skips building and returning a reply.

This is primarily aimed at lokinet which polls fairly frequenty for an
update but where the vast majority of those polls contain no new
information.

It also removes the get_all_service_nodes_public_keys RPC request
completely as lokinet was the only consumer of it (particularly unlikely
that anyone else was using this because it was returning the keys
base32z-encoded).
2019-11-08 03:01:08 -04:00
Doyle c859a2ab96
Merge pull request #914 from Doy-lee/HandleTXRemoveUselessStep
Remove check_tx_syntax unused since forever
2019-11-07 16:30:43 +11:00
Doyle 1e46dd48c5
Merge pull request #920 from jagerman/tx-burning
Tx burning
2019-11-07 12:24:13 +11:00
Jason Rhinelander a9294cdbef Remove boost::value_initialized and BOOST_FOREACH (#921)
Neither of these have a place in modern C++11; boost::value_initialized
is entirely superseded by `Type var{};` which does value initialization
(or default construction if a default constructor is defined).  More
problematically, each `boost::value_initialized<T>` requires
instantiation of another wrapping templated type which is a pointless
price to pay the compiler in C++11 or newer.

Also removed is the AUTO_VAL_INIT macro (which is just a simple macro
around constructing a boost::value_initialized<T>).

BOOST_FOREACH is a similarly massive pile of code to implement
C++11-style for-each loops. (And bizarrely it *doesn't* appear to fall
back to C++ for-each loops even when under a C++11 compiler!)

This removes both entirely from the codebase.
2019-11-01 09:26:58 +11:00
Jason Rhinelander 1e496975b3 Add fee burning
This adds a tx extra field that specifies an amount of the tx fee that
must be burned; the miner can claim only (txnFee - burnFee) when
including the block.

This will be used for the extra, burned part of blink fees and LNS fees
and any other transaction that requires fee burning in the future.
2019-10-30 18:47:22 -03:00