greffe — a heron keeping the ledgers
a lightweight blockchain · proof of authority · no money

greffe

A lightweight blockchain for associations, cooperatives and collectives — any group where transparency matters and nobody should be able to quietly rewrite the record. Signed entries, hash-chained blocks, replicated on the machines the group already has, verifiable by anyone from genesis. No money, no mining.

What it is, in numbers

1federation in production: a village materials library, two validators on two machines
5 MBresident memory of an idle node or relay (static binary, 5.3 MB on disk)
1TCP port for peers and the HTTP API — nothing else to open
0tokens, mining, or empty blocks. An idle federation costs nothing
50blocks of settled history a node will never let a fork rewrite (max_reorg), whatever its weight

A blockchain with the expensive parts removed

What a blockchain is for: an append-only record where every entry is signed by its author and every block is chained by hash, so tampering is visible and the whole history can be re-verified by anyone. What greffe leaves out: currency, mining, staking, gas, a global permissionless network. The group already knows whom it trusts — its own servers — so those seal the blocks, and adding one is a signed entry, not a fork.

Federations

An umbrella body and its member associations, each keeping a node, each able to prove what was decided.

Cooperatives

Members are owners: decisions, membership and contributions on a register every member can read and check.

Collectives & commons

Open-source projects, community networks, mutual-aid groups — anyone who provides shared tools and wants its governance on the record.

The model

Entries

Signed records {id, author, ts, kind, payload, sig}. kind is free text (a decision, a tool release, a grant); payload is any text, JSON encouraged. The id is a hash of the content, the signature is Ed25519 over the id.

Blocks

Validators — the association's servers — seal blocks in Clique-style round-robin. The in-turn validator seals immediately; the others wait block_interval × distance, so an offline server never stalls the chain.

Fork choice

Highest total weight wins (in-turn block = 2, out-of-turn = 1), ties by lowest tip hash. Deterministic, so nodes converge without talking to everyone. Settled history is off limits: a fork that would rewrite more than max_reorg blocks is refused, however heavy — a validator cannot re-seal the past.

Governance on-chain

validator.add / remove and member.add / remove are ordinary entries signed by a validator. Genesis fixes only the name, a timestamp and the first validators; everything after is in the record itself.

Two machines, no single point of failure

A chain does not need a connection forwarder. Every block and entry is signed, so any public node is a meeting point: a node behind NAT pushes what it has and pulls what it lacks. A relay holds no key, cannot forge anything, and can only withhold — which a second node defeats with no coordination, because fork choice reconciles them. In the production federation the second node is a validator on an independent machine, which also means a rewrite would need both keys.

In production — the register of the matériauthèque of the Cœur des Bauges enbauges.fr ──► bkn hook ──POST /put──► validator A (site server, :7421) ▲ │ seals in turn, refuses rewrites residents read /registre/ui ────────────┘ ▼ validator B (independent VPS, :7421) A member node behind NAT would dial either validator (relay mode) and subscribe for pushes; if both are down, nothing is lost — writes wait as pending and reconcile when one returns.

Documentation for humans

How it works

Entries, blocks, validators, forks and relays in plain language, for the people who will rely on the record.

Security & threat model

Exactly what is guaranteed, by what mechanism, against whom — and what is not.

Running a node

Install, roles, systemd, firewall, files to back up, watching it, upgrading, and what to do when things go wrong.

Governance

Bootstrapping a federation, admitting and revoking, key rotation, and the conventions a group should agree on.

Use cases

Federations, cooperatives, open-source collectives, community infrastructure, cross-organisation notarisation — with entry conventions.

FAQ

Is it a cryptocurrency? Who decides? What if we lose a key? Is it audited?

In use: the matériauthèque of the Cœur des Bauges — residents of fourteen villages give or lend materials and tools to each other — records every object published, lent or gone in a greffe federation you can open right now: the register. Details in use cases.

examples/federation.sh plays the reference use case on your machine in about a minute: an umbrella validator, a relay, two member associations, a charter, a decision, a release, a subsidy, a refused outsider and a revocation.

Quick start

./build.sh                     # needs machin; STATIC=1 ./build.sh for a portable binary
greffe init --name my-federation --port 7420     # first validator, keys in ~/.greffe
greffe serve                                     # or the systemd unit in deploy/

# a second machine that can reach the first one
greffe init --join http://first-node:7420 && greffe serve

# a public relay, and a machine behind NAT, from the published genesis
greffe genesis                                   # -> {"name","genesis_ts","validators","hash"}
greffe init --relay --genesis '<json>' --port 7420 --peers other-relay:7420
greffe init --nat   --genesis '<json>' --peers relay1:7420,relay2:7420
# a site's own register: explorer + server-side writes, served under one path of the site's domain
greffe init --ui --put-token auto --base-path /registre

# then, from any node whose key is a validator or member
greffe grant member <pub>                        # governance = a signed entry
greffe put --kind decision --payload '{"title":"adopt greffe"}' --wait
greffe entries --kind decision
greffe verify                                    # exit 0 ok / 90 broken

Every command prints JSON. greffe guide or GET / on a node describes the HTTP API: /status /peers /blocks /entries /pending /verify and POST /entries.

A public ledger needs a public window

Any node can serve a read-only explorer at /ui — opt-in with greffe init --ui. Overview, blocks, entries with kind and author filters, a governance view of who was admitted or removed and by whom, the pending queue, peers, and a button that re-verifies the whole record from genesis on that node. It is one page baked into the binary, talking to the same JSON API agents use; writes stay in the CLI, where the keys are. Public relays keep a per-IP rate limit (300 requests per 10 s by default) so an explorer on the open internet stays cheap to run.

Live explorer on the reference relay — the federation used to develop greffe, warts and all.

Gentle on the machines it runs on

machin keeps a per-goroutine arena, which means a long-running single-actor loop must manage its own memory. greffe holds blocks as raw JSON lines plus small headers, parses entries on demand inside scoped arenas, and resets its arena when resident memory grows, rebuilding state from disk. The benchmark that found the original leak is in the repo.

Scenario (2,000 writes, 20 parallel writers)BeforeAfter
Two validators, direct1.6 GB per nodepeak 56–72 MB, settles ~20 MB
Two NAT'd validators through a relayrelay peak 35 MB, resets to 15 MB
300 live writes across the public internetrelays peak 27 MB, settle 6.5 MB

What is verified, and what is not

test.sh covers sealing, sync, the membership gate, grants, two-validator round-robin, partition catch-up, restart persistence, the explorer, the filters, the authenticated write endpoint and the rate limit. test-relay.sh covers subscriptions, relay failover, a no-relay hold, relay recovery and fork convergence through relays. test-reorg.sh proves a node keeps its settled history against a heavier rewrite. machin check reports zero data-race diagnostics: one event loop owns all state.

What the production deployment does not yet prove: both validator keys are held by the same team until a member association runs the second node. The page that uses the register says so in as many words.

Not yet: TLS between peers (use Tailscale or WireGuard), per-author quotas, pruning of old blocks from memory.