Skip to content

Cactus pollinate - #12

Merged
mcpherrinm merged 6 commits into
mainfrom
cactus-pollinate
Jul 22, 2026
Merged

Cactus pollinate#12
mcpherrinm merged 6 commits into
mainfrom
cactus-pollinate

Conversation

@mcpherrinm

Copy link
Copy Markdown
Owner

This is a tool for syncing mirrors

Generate §4.4 subtree consistency proofs from stored interior node
hashes (the tlog.StoredHashIndex addressing scheme) instead of hashing
every leaf. O(log n) node reads per proof makes generation over a
remote tree practical: each read maps to a cached, authenticated
hash-tile lookup rather than a replay of the whole log.

The existing leaf-hashing generator is unchanged; both share the
SUBTREE_PROOF skeleton, parameterised by a range-hash function.
A c2sp.org/tlog-cosignature log_origin is just the checkpoint origin
string, and real-world MTC logs (e.g. Cloudflare's bootstrap CA, origin
bootstrap-mtca.cloudflareresearch.com/logs/shard3) use plain
hostname-path origins that TrustAnchorID cannot represent. Expose the
§5.3.1 CosignedMessage construction with raw string names;
MarshalSignatureInputAt becomes a thin wrapper.
Target.Origin overrides the oid/-derived checkpoint origin so the push
client can serve logs whose origin is not a trust anchor ID, and
VerifyCosignaturesForOrigin verifies mirror cosignatures against such
origins (VerifyCosignatures delegates to it).

The 404 responses from add-checkpoint and add-entries now wrap a new
ErrUnknownOrigin sentinel, so a caller that pushes opportunistically
can record "this mirror does not carry this log" with errors.Is
instead of treating the response as an operator-facing fault.
cactus-pollinate follows the Chrome MTC cosigners list, watches every
issuer's logs and every mirror's copy of them, and pushes missing
entries (via the c2sp.org/tlog-mirror write API) to any mirror that has
been lagging the log head for longer than a configured delay. CAs are
expected to push on their own; pollinate is the backstop for mirrors
they are failing to reach — including bootstrapping brand-new mirrors.

Discovery probes both layouts seen in the wild: a single log at the
bare CA base URL and mtc-tlog-profile logs at <CA prefix>/<n>. A log's
identity is the origin its checkpoint declares, including non-oid/
origins. Reads go through tlog.TileHashReader, so every hash and entry
is authenticated against the source checkpoint root without keeping a
local replica (Cloudflare's bootstrap log has 229M entries); sources
are picked freshest-first with random tie-breaks to spread read load,
and verified tiles are shared through a bounded cache.

Lag is measured against history, not the current head: the state file
(pollinate/state.json) records when the head was first seen at each
size, and a mirror is only pushed entries the head already had a full
delay window ago. Mirrors that answer "unknown origin" on the
submission API are recorded as not carrying the log and rechecked on an
interval or when the cosigners list version changes.

Issuer checkpoints are signature-verified when the key is ML-DSA-44;
mirror cosignatures on push responses are always verified, with keys
matched from the cosigners PEM bundle by key_sha256 (the SHA-256 of the
SPKI DER). Prometheus metrics (cactus_pollinate_*) and slog JSON output
follow the cactus server's conventions, including loopback-gated pprof.

Tested end-to-end against a stub mirror that verifies every pushed
subtree consistency proof, and live against a real Sunlight
witness/mirror (562-entry bootstrap push, cosignature verified, mirror
copy recomputes to the CA's signed root).
c2sp.org/tlog-tiles: clients SHOULD include a way for the operator to
contact them in the User-Agent (an email and/or a +https:// URL), and
logs MAY rate-limit anonymous or unreachable clients. Skylight enforces
this — anonymous entry-bundle reads get HTTP 429.

Stamp a contact UA on everything in the repo that talks to a log or
mirror: the cactus server's mirror_push client and sign-subtree quorum
requests ("cactus (+https://github.com/mcpherrinm/cactus)") and
cactus-cli's reads. cactus-pollinate already ships with its own. The
integration stub witness now records the User-Agent it sees so the
header cannot silently regress.
@mcpherrinm
mcpherrinm merged commit e8d6ae7 into main Jul 22, 2026
2 checks passed
@mcpherrinm
mcpherrinm deleted the cactus-pollinate branch July 22, 2026 05:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant