
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 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.
An umbrella body and its member associations, each keeping a node, each able to prove what was decided.
Members are owners: decisions, membership and contributions on a register every member can read and check.
Open-source projects, community networks, mutual-aid groups — anyone who provides shared tools and wants its governance on the record.
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.
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.
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.
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.
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.
greffe init --nat --peers relay1:7420,relay2:7420. It advertises no port, keeps one long-lived subscription per relay for pushed blocks and entries, and syncs over its own outbound dials.greffe init --relay --genesis '…' on a public host. Accepts up to 256 subscribers, pings them every 30 s.Entries, blocks, validators, forks and relays in plain language, for the people who will rely on the record.
Exactly what is guaranteed, by what mechanism, against whom — and what is not.
Install, roles, systemd, firewall, files to back up, watching it, upgrading, and what to do when things go wrong.
Bootstrapping a federation, admitting and revoking, key rotation, and the conventions a group should agree on.
Federations, cooperatives, open-source collectives, community infrastructure, cross-organisation notarisation — with entry conventions.
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.
./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.
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.
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) | Before | After |
|---|---|---|
| Two validators, direct | 1.6 GB per node | peak 56–72 MB, settles ~20 MB |
| Two NAT'd validators through a relay | — | relay peak 35 MB, resets to 15 MB |
| 300 live writes across the public internet | — | relays peak 27 MB, settle 6.5 MB |
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.