Commit Graph

72 Commits

Author SHA1 Message Date
cloudhead 3ad84420bd
cli: Implement `rad cob migrate`
Adds the new `migrate` sub-command to migrate the COB database.
Checks for version when opening the COBs database and suggests the
command on out of date version.

Also adds the 2nd migration to the COBs cache, which updates the patch
JSON schema.
2024-11-22 21:27:45 +01:00
cloudhead c6a8a00055
Update `rust-toolchain` to 1.80
Fix new clippy warnings.
2024-08-06 14:37:21 +02:00
Lorenz Leutgeb 723e2741f5
node: Socket Activation with systemd 2024-07-22 10:44:22 +02:00
Derick Eddington 6f8d75a00d
node: Fix "signals" thread
Fix "signals" thread to continue upon other signals.

Otherwise, previously, when one of the non-shutdown signals was
received, that would cause the "signals" thread to finish, but then a
subsequent signal that should cause shutdown would not because the
thread no longer existed to do so.  E.g. when SIGHUP or SIGWINCH was
received first and ignored and then SIGTERM or SIGINT was received next,
the program should still be shutdown, but it wouldn't be.  This is now
fixed by simply looping to continue handling subsequent signals.

Logging is now done for:
- Receiving of SIGHUP, at log level `debug`, because the default action
  for that signal would be to terminate the process but that is not done
  by `radicle_signals`.  Someone sending that signal might want to debug
  why the process isn't being terminated.
- Disconnection of the signal-notifications channel, at log level
  `warn`, because, even though that should be impossible, if it somehow
  occurs then a warning is warranted.

Logging is not done for receiving of SIGWINCH, because the default
action for that signal would be to ignore it, which is what
`radicle-node` does.

A wildcard pattern is not used in the match arms, so that any future
changes to the `Signal` variants will require reviewing their handling
in the "signals" thread.

Signed-off-by: Derick Eddington <kcired@pm.me>
2024-07-22 10:38:42 +02:00
cloudhead f7d8f1b8da
radicle: Distinguish seeding policy types
We create a separate type for the default seeding policy, that
serializes differently and is only used in the node configuraiton.
2024-06-26 11:57:04 +02:00
cloudhead a89a300390
node: Pass `Alias` by reference 2024-06-13 11:28:09 +02:00
cloudhead 76edc0c523
node: Add agent and version to node announcement
1. Adds a user-agent string to the node announcement. This lets us keep
   track of what software version everyone is running. Especially useful
   to see what percentage of the network has upgraded to a new release.

  For old nodes, this defaults to the string `/radicle/`.

  The user agent format is roughly based on BIP 0014.

2. Advertize protocol version in node announcement.

  By advertizing the protocol version, nodes can decide to only connect to
  peers with a compatible version. The default and current version is `1`.

  We bundle these two changes as they both modify the node announcement
  and node database.

3. Swap the order of the fields in announcements to make the message
   extensible.
2024-06-13 11:28:09 +02:00
cloudhead 5c0d1b10e0
node: Make sure all channels we use are bounded
This prevents potential memory leaks. We also ensure that sends fail
instead of blocking, in case the channels are full.

Additionally, we add some metrics to report on channel size.
2024-06-12 19:00:23 +02:00
cloudhead b24f8a30d6
node: Update inventory when unseeding
Previously, our advertized inventory was not always correct: when we
stopped seeding a repository, it was still advertised as part of our
inventory until node restart, because the `Storage` type doesn't have
access to seeding policies.

In this change, we remove the concept of inventory from `Storage` and
make the authoritative place for it the routing table in our database.

To make this work, we have to add our node to the database on profile
creation, to not violate the foreign key constraint on the routing
table. Hence, the tests are changed to include our alias which is now
always available.
2024-06-12 15:36:34 +02:00
Alexis Sellier 3ae7e305bd
node: Simplify configuration
This is a change to the `config.json` file which removes certain options
that are best not touched and changes some options to make them easier
to work with.

1. We change the default journaling mode to "wal" and remove the config
   option.
2. We remove the option to set the peer connection "target", as it's not
   a good idea to set this to a different value, as it affects the
   network.
3. We combine seeding policy & scope, since there's no need to set the
   scope when the policy is "block". In that case, we always want to
   block "all" remotes. The new policy configuration has the following
   schema:

   { seedingPolicy: { default: "block" | "allow", scope?: "all" | "followed" } }

   The "scope" key is not used when "default" is set to "block".

4. We add an `extra` field to the node config for options that are not
   recognized. We use this to warn the user.
2024-06-04 14:08:15 +02:00
Fintan Halpenny f0648c2a18
radicle: move Emitter to events module
Move the events Emitter to the `radicle::node::events` module to allow it to be
used outside of `radicle-node`.

Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
2024-05-15 10:07:56 +01:00
cloudhead 21cced05c1
node: Allow for "WAL" mode in sqlite
This solves concurrency issues between the node and http daemon.
2024-05-14 16:34:30 +02:00
cloudhead 7484d737d5
node: Re-use inventory message timestamps
If our inventory hasn't updated, don't issue a new inventory
announcement, simply use the previous message.

This avoids identical inventories propagating over the network and using
up resources.
2024-05-07 14:49:02 +02:00
cloudhead 2801403182
signals: Move signal handling to its own crate
We're going to share this code with `radicle-term`.
2024-05-03 14:30:51 +02:00
cloudhead 7126d05130
node: Use constant delay for refreshing node ann
We use a shorter, constant delay, so that it is the same on all nodes.
2024-04-29 12:49:59 +02:00
cloudhead deeb39c558
node: Support "transparent" Tor
This allows for configuring your node such that `.onion` addresses
encountered are treated as regular DNS names.
2024-04-26 10:37:41 +02:00
cloudhead 2b771921d5
node: Type-safe timestamps
Use a struct to represent timestamps, to improve type safety.
2024-04-24 12:19:40 +02:00
cloudhead 256c620d31
node: Use refs cache to decide on fetching
When deciding whether or not to fetch a repo based on a refs
announcement, we need to know whether our signed refs are stale or not,
compared to the ones in the announcement. This can be quite expensive as
it requires multiple reads from Git's ODB, which often results in
packfile loading.

To remedy this, we introduce a refs cache in our node database that is
consulted when an announcement is received.

We also remove the logic that generates `info` messages, since they are
rarely needed and introduced more complexity.

Additionally, we revert commit 3ad2b4431f,
which introduced logic to minimze wants and haves with additional logic,
since it potentially also increases the load on the ODB.
2024-03-29 16:00:33 +01:00
cloudhead 0e880e12e6
node: Cache node inventory
For large seeds with many repos, it's expensive to traverse the
inventory everytime the node connects to a new peer, for example.

To improve the situation, we cache the inventory per `Storage` instance,
and add a `refresh` method to refresh the inventory.

This method is called when the node is told to synchronize its
inventory.
2024-03-21 12:40:58 +01:00
Alexis Sellier ddd4bde302
node: Make worker count configurable 2024-03-19 16:34:15 +01:00
Fintan Halpenny 4d50f79f1c
node: remove unused timeout
The timeout was never being used, so it is being removed for the time
being.

Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
2024-03-11 11:28:38 +01:00
cloudhead 9c9bbbe7bb
node: Expose listen addresses 2024-02-26 12:35:20 +01:00
Fintan Halpenny 985b0af3f6
radicle: implement caching for issues and patches
Implement caching for the `Issue` and `Patch` COB. This is achieved by
having the `Transaction::initial` and `Transaction::commit` methods
take a cache which can update the newly created/updated object. The
`Store::remove` method also takes the cache for removing the object
from the cache, as well as the repository.

This meant that the `*Mut` types for the respective COBs are required
to carry a cache alongside the repository store. Identities will not
be cached, and so this is always set to `NoCache` -- which performs no
caching, and always succeeds.

To perform cache reading for issues and patches, the `cache::Issues`
and `cache::Patches` traits are introduced. They capture the minimal
amount of methods that are needed for the `rad issue` and `rad patch`
CLI commands.

The implementor for each of these traits is there respective `Cache`
types, which combines their backing repository store and the SQLite
database. They both provide convenience methods:
- `create` (and `draft` for patches)
- `get_mut`
- `remove`
which can be used instead of their repository store counterparts.

All uses of the repository stores (where needed) are replaced with
`Cache` types.

Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
2024-02-23 16:03:21 +01:00
cloudhead fe55de181d
cli: Add new `rad inbox` command
Shows you updates on local repositories.

Included here is a basic implementation of a notification system. A new
database is created and updated after every fetch, with refs that have
changed.

The `rad inbox` command can then list items in the database and delete
them.
2024-02-06 11:40:58 +01:00
cloudhead 98c94de5e3
Various small improvements across crates
Most of these changes should be self-explanatory.

* Atomic fetch was no longer used
* The default policy when initializing should be 'all', as it is with
  `rad init`.
2024-02-06 10:37:44 +01:00
cloudhead 073c55fa3b
node: Don't panic on initialization error 2024-01-10 15:23:05 +01:00
cloudhead 99aeae19ea
node: Fix node announcements not being received
Since node announcements are stored and retrieved from disk (due to the
PoW), the timestamp on it is never updated. This means it can be too old
to cache and not sent/received by nodes. Fix this by having a max age.
2023-12-14 10:41:59 +01:00
Fintan Halpenny 63469fd3bc
node: init policies DB early
Instead of creating the DB policies handle when needed, construct the
handle when the `Worker` pool is being constructed.

This replaces the usage of the DB handle with the `Worker`'s field
instead.

Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
2023-12-13 14:20:15 +01:00
cloudhead 6ca7da2768
radicle: Rename many more methods using new naming 2023-12-06 10:02:00 +01:00
cloudhead 1b026ae0ee
node: Rename node `tracking` module 2023-12-06 10:00:45 +01:00
cloudhead 6b04eff34c
radicle: Consolidate databases
Instead of having a routing database, and an addresses database,
consolidate that in a single database called `node.db`.

We also simplify database access, by providing a single type for opening
the database, and use traits to access the various functions.

We create a new `seed::Store` that has seed-related methods split out of
the `address::Store`.

Note that tracking is still in its own database currently, as it isn't
ephemeral state. This makes it easy to delete the new `node.db` without
risk of losing any important information.

To avoid renaming all database methods, we create a `Stores` wrapper
that allows us to access routing, addresses, seeds etc. without type
ambiguity.

This is a breaking change and requires `addresses.db` and `routing.db`
to be deleted.
2023-11-30 13:00:59 +01:00
cloudhead d4ec2176bb
Update Rust toolchain to 1.74 2023-11-17 16:58:24 +01:00
Fintan Halpenny e71f07e592
radicle: temporary repository helper
It's possible that a temporary directory can be created on a different
mount, and when moved during a clone, creates an I/O error.

To prevent this, add a method to `Storage` which creates a temporary
directory and `Repository` with the path in the form
`<rid>.lock`.

This `.lock` path name can easily be skipped when listing
repositories. Further tooling can be added for detecting leftover
`.lock` directories if, for some reason, they were not cleaned up by
the `tempfile` crate.

Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
2023-11-16 12:01:10 +00:00
cloudhead 3cad39a3a9
node: Fix timestamp bug
We were using seconds when it's supposed to be milliseconds. Oops.
We should probably switch this type to `LocalTime` at some point.
2023-11-13 15:57:03 +01:00
Fintan Halpenny cf08a3f731
node: run git gc on fetch
It is desirable to keep the Git repositories in Radicle efficient by
ensuring objects are packed and unreachable objects are removed.

Add a process call to `git gc` to achieve this. Two flags are used for
garbage collection: `--auto` and `--prune`. Their details are outlined below:

       --auto
           With this option, git gc checks whether any housekeeping is
           required; if not, it exits without performing any work.

       --prune=<date>
           Prune loose objects older than date (default is 2 weeks
           ago, overridable by the config variable
           gc.pruneExpire). --prune=now prunes loose objects
           regardless of their age and increases the risk of
           corruption if another process is writing to the repository
           concurrently; see "NOTES" below. --prune is on by default.

For `--prune` the default used is `1.hours.ago`. This was chosen over
`now` since that may be too aggressive after just fetching new data.

Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
2023-11-10 11:44:25 +01:00
Fintan Halpenny 82a53e3a53
radicle: UserInfo for Repository::create
The fetch V2 improvements introduced a `UserInfo` type that is used to
set the Git config's name and email when cloning a repository. This
`UserInfo` can also be used when creating a new `Repository`.

The `Storage` type now takes a `UserInfo` so that it can be passed to
`Repository::create`, for creating a new repository.

For testing, this requires adding a new `fixtures::user` so that
testing `Storage` instances can be easily constructed.

It also means that the `radicle-cli` tests all changed with new SHAs
since the name and email are used as part of the hashing input.

N.b. the order of the timelines while testing the identity cob
changed. It's not clear why that is.

Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
2023-11-09 16:43:34 +01:00
cloudhead f9df360171
node: Persist historical gossip messages
Instead of storing received gossip messages in an in-memory `BTreeMap`,
we persist them to the database (`addresses.db`). There are two reasons
for this:

1. Node restarts do not wipe the state, meaning that it is much less
   likely that some gossip message will get lost before reaching all
   nodes.
2. This will allow us in the next commit to know how far behind we are
   after a restart, to be able to request the correct time range of
   gossip messages that we missed while offline.

Note that we now share the addresses.db file between two connections and
stores, which we don't do anywhere else. Having multiple connections to
the same database is fine, but the way we're having to do it is a bit
awkward. In a future patch, we could pull out the database schema from the
`address` module and rename the database to make things clearer.
2023-11-08 13:15:56 +01:00
Fintan Halpenny d7abc0a8fc
node: remove git-daemon code
The git-daemon code is no longer needed since git-upload-pack is used
in its place.

Remove the git-daemon code from the runtime and worker.

Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
2023-11-06 12:07:27 +01:00
Fintan Halpenny ea7f26dbdf
radicle: wire up radicle-fetch
Wire up the `radicle-fetch` crate to the fetch logic in the
`radicle-node` worker.

Any required traits for storage, identity, tracking, and transport
used by `radicle-fetch`.

The worker adds a new module to run the `git upload-pack` process and
pipes the `stdout`/`stdin` to the respective channels.

The `Worker` type required adding a `FetchConfig` to easily allow the
configuration of fetches and passing the signer and tracking store
location through to the fetch `Handle`.

The channels code is adapted to have a new writer that always flushes
when a call to `write_all` is made. This is necessary since the
Gitoxide code never calls `flush`, and so it will hang since no data
is sent until `flush` is called.

Since `UserInfo` is used to set up a newly cloned repository, this
changed some of the SHA1 hashes output in the CLI test examples. It
was also necessary to update the CLI's clone code to be deterministic
in its output for tests.

Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
2023-11-06 12:06:13 +01:00
cloudhead e888398519
node: Populate address book with bootstrap nodes
As a starting point, we populate the address book (if empty) with some
bootstrap nodes which are trusted.

To prevent these nodes being connected to during tests (including e2e
tests), we create a new constructor for `Config` that is used in tests.

Note that a `cfg(test)` check is not enough given that e2e tests don't
have that set.
2023-08-09 12:39:33 +02:00
Alexis Sellier eb701be033
node: Make node aliases required
This is a fairly substantial change, which adds a new configuration file
to the user's `$RAD_HOME` that includes node configuration, including
the alias, and also makes node aliases required.

When running `rad auth`, the user is now prompted for an alias, which
defaults to `$USER`.

When running `rad self`, the alias is now shown.

If the user runs radicle without a config file, the defaults are loaded,
and `$USER` is used as the alias.
2023-07-11 18:08:59 +02:00
Alexis Sellier bb099faa4f
node: Give useful thread names
For the purposes of debugging running nodes, it's useful to know which
threads are doing what. This allows tools like `htop` to reveal which
threads are running.
2023-06-20 11:18:14 +02:00
Alexis Sellier 91404e4c37
node: Fix regression on control socket delete
The removal of the control socket on shutdown was mistakenly taken out.
We add it back here.
2023-06-07 11:39:23 +02:00
Alexis Sellier ff7338de17
node: Always send node announcement on handshake
Previously, we only sent the announcement when there were external
addresses. But it contains other information like the node alias,
therefore we always send it.

Since the proof-of-work can be expensive to compute everytime, we add
the ability to load the local node announcement from the file system.

We also change the proof-of-work parameters so that they are relaxed
when running in debug mode, instead of when running tests.

Finally, we remove the boolean validation of the PoW. Instead, we store
the work per-node, in the database, to be used in the future in case of
DoS attacks or network congestion.
2023-06-07 11:39:23 +02:00
xphoniex f526465f1b
radicle: Make addresses.db accessible from profile
Signed-off-by: xphoniex <dj.2dixx@gmail.com>
2023-06-02 14:49:20 +02:00
Alexis Sellier c400961cec
Update `io-reactor` and related dependencies 2023-05-27 20:43:56 +02:00
Alexis Sellier 664aa570e6
node: Spawn a thread for each control connection
Previously, only one connection to the node control socket could be
handled at a time. This usually worked fine, but if one connection hangs
for whatever reason, no other process can access the node.
2023-05-24 11:33:55 +02:00
Alexis Sellier ac3a03fea6
node: Set git-daemon keep-alive
Send a keep-alive packet every 3 seconds to make sure the client doesn't
timeout during pack building.
2023-04-14 13:15:52 +02:00
Alexis Sellier f3d513783c
node: Don't fetch owned refs unless cloning
We shouldn't be fetching our own refs unless we are creating a clone.
2023-04-12 16:40:53 +02:00
Alexis Sellier 89b9eb53b7
node: Implement protocol multiplexing
To improve the reliability and flexibility of the protocol, we introduce
multiplexing over peer connections. This involves a new `Frame` type
that carries a stream-id and payload.

Three stream types are made available:

1. Control
2. Gossip
3. Git

This change brings the following improvements:

* Removed need to queue fetch requests
* Removed need to queue gossip messages
* Removed need for `Fetch` and `FetchOk` messages
* Service doesn't need to know about inbound fetches
* Removed one round-trip for fetch negotiation
* Removed special `done` git packet
* Removed session logic and state around Git/Fetch protocols
* Removed code around upgrading/downgrading transport
* Worker in responder mode is able to process any number of fetches
* Connections support any number of concurrent fetches

We had to introduce a few extra things however to make it all work:

* A `VarInt` type for variable-length integers, since we want the frames
  to be lightweight.
* A custom "tunnel" implementation, since we couldn't use the existing
  one anymore.

Overall the change removes more complexity than it adds, while improving
the protocol along the way.
2023-04-10 14:41:55 +02:00