Architecture overview

After 0.0.8. Gridnodes, network storage, the ledger, the S3 endpoint and the SOCKS proxy are on the master branch and not part of a release yet. A 0.0.8 node finds peers, shares sporks and serves the legacy chain snapshot. Release 0.0.9 leaves those parts off, and the hidden daemon switch --preview turns them on for development and testing.

Hedgehog is the software that runs the Unigrid peer-to-peer network. Each computer that runs it becomes a node that finds other nodes, agrees with them on signed network settings and, on gridnodes, helps store files that its users can retrieve later. One program does all of this, so anyone can run a node, operate it from the command line, or build on top of it.

What a node does

  • Joins the network. A node connects to other nodes over QUIC, an encrypted transport built on UDP. It starts from six seed hosts and learns more peers from the ones it meets. See Peer-to-peer network protocol.
  • Shares network settings. Parameters such as the maximum supply and the storage layout travel as sporks, small records signed by the board keys. A change takes effect only when two different keys active now have signed it, and nodes pass accepted changes on to their peers without a voting round. See Grid sporks.
  • Stores files. A file is encrypted, split into small erasure-coded fragments and spread over the gridnodes, which repair lost fragments among themselves while the owner is offline. The network keeps no index of files, and only the holder of a file’s fingerprint can read or delete it. See Network storage and Erasure coding.
  • Serves S3 and SOCKS. With --preview, a local S3 endpoint keeps buckets and objects in network storage, and a local SOCKS proxy, off by default, carries TCP and UDP traffic out through a gridnode.
  • Runs the ledger. With --preview --ledger a node follows, and on a validator signs, the blocks of the Ledger.
  • Takes commands. A local REST interface lets an operator inspect and steer the node, and the hedgehog cli command is a thin client of that interface. See REST interface.
  • Reads the legacy chain. The hedgehog bootstrap commands turn the foundation’s older chain data into a signed snapshot that anyone can verify. See Legacy chain snapshot.

How it fits together

The same program becomes a daemon, a client or a key utility depending on the command it is given.

flowchart LR
    OP["Operator<br/>hedgehog cli ..."] -->|"HTTPS + token"| REST
    subgraph NODE["hedgehog daemon: one process"]
        REST["REST server"]
        P2P["Peer-to-peer server"]
        TOP["Known peers"]
        SP["Sporks, saved to disk"]
        ST["Storage service"]
        REST --> TOP
        REST --> SP
        REST --> ST
        P2P --> TOP
        P2P --> SP
        P2P --> ST
    end
    P2P <-->|"QUIC"| PEERS["Other nodes and seeds"]
  • hedgehog daemon starts the node and keeps it running. On shutdown it saves the spork database to disk.
  • hedgehog cli talks to a running daemon through the REST interface and never joins the peer network itself.
  • hedgehog util generates, signs with and validates keys without needing a daemon.
  • hedgehog bootstrap builds and queries the legacy chain snapshot.
  • hedgehog s3, hidden from --help, manages the access keys of the S3 endpoint, which runs only with --preview.

Six Maven modules make up the project: application holds the daemon, its commands and its servers, common only the version and data-directory helpers, ledger the ledger, proxy the SOCKS proxy, s3 the S3 endpoint, and native-image wraps the program and a Java runtime into one executable. The component wiring and startup order are described in CDI container and component lifecycle, and the build and test tooling in Build, testing and native image.

Within application, model holds the data, the known peers, the packets and their codecs, and the option classes that the commands parse. The services, servers, clients and commands build on model. transport holds the handlers, pipelines and schedules of the peer streams that the servers and clients set up, and producer makes the shared objects for the container. Both call the services, which depend on neither. A test fails the build on a cycle between packages, or when model depends on a command, service, server or client.

Trust

  • Network settings are authenticated. A node accepts an ordinary spork only with two different signatures from keys active now, and checks each signature in its history against a key that was ever a board key. The board keys spork is judged by its own chain instead, which replaces the keys without a release. The four built-in keys belong to the Unigrid Foundation board and can be replaced with --network-keys, which is how a private network is set up.
  • The control interface is local and needs a token. The REST server listens on localhost by default, and every request must carry a bearer token that the daemon writes to rest.token in its data directory.
  • Transport encryption does not identify the other side. Both the peer and the REST connections use self-signed certificates that the bundled clients accept without checking, so they protect against eavesdropping but not against an active attacker in the middle.

Key facts

Fact Value
Language and runtime Java 25
Peer-to-peer port 52883 over UDP, bound to all interfaces (-p, -H)
REST port 52884 over HTTPS, bound to localhost (-r, -R)
Seed hosts seed1 to seed6 at unigrid.org; --no-seeds turns them off
Wire protocols hedgehog/0.0.9, hedgehog/0.0.4 and gridspork/0.0.4; with --preview hedgehog-proxy/0.0.2 ahead of them, and hedgehog-ledger/0.0.2 first on a ledger node
Change signed by one key Expires after 60 minutes unless a second key co-signs it
Gridnode announcement Renewed every 5 minutes
Storage sizes 1 MiB chunks cut into 64 KiB fragments, the storage spork defaults
Largest REST upload 64 GiB, through /storage
Data directory on Linux ~/.local/share/hedgehog, holding spork.db and its lock spork.db.lock, copies spork.db.unsigned-<epoch seconds>, rest.token, ledger/ and s3/, see Running Hedgehog
S3 endpoint Port 52885 over HTTPS, bound to localhost, on by default with --preview (--s3port, --s3host, --no-s3) and off without it
SOCKS proxy Off by default; --preview with --socks-port turns it on, bound to 127.0.0.1

In the source

All paths are relative to the repository root.

  • application/src/main/java/org/unigrid/hedgehog/Hedgehog.java, the entry point and root command
  • application/src/main/java/org/unigrid/hedgehog/command/, the daemon, client, key, bootstrap and S3 commands
  • application/src/main/java/org/unigrid/hedgehog/server/p2p/P2PServer.java, the QUIC server
  • application/src/main/java/org/unigrid/hedgehog/transport/, the handlers, pipelines and schedules of the peer streams
  • application/src/main/java/org/unigrid/hedgehog/server/rest/RestServer.java, the REST server
  • application/src/main/java/org/unigrid/hedgehog/model/network/Topology.java, the known peers
  • application/src/main/java/org/unigrid/hedgehog/model/spork/, the signed network settings
  • application/src/main/java/org/unigrid/hedgehog/service/storage/StorageService.java, the storage entry point