dig-node native Chia §21.9 signer + auth sync, dig-wallet send/sign, dig.getAnchoredRoot#1
Merged
Conversation
…re sync
The DIG Browser's dig-node sidecar proxied rpc.dig.net's dig.getContent
unauthenticated and could not populate its module cache from the §21
GET /stores/{id}/module endpoint (it 401s for anonymous clients). dig-node
now carries a native Chia identity signer (paper §21.9): on a local
module-cache miss for a concrete (store, root) it fetches the whole .dig
module over the authenticated §21 endpoint — stamping
X-Dig-Identity/-Timestamp/-Nonce/-Auth exactly like the digstore CLI — caches
it, and serves every subsequent resource in that store locally.
To authenticate "the same way the CLI does", the persistent identity key
(seed + seed→BLS-key derivation + RequestIdentity construction) is extracted
into a shared digstore_remote::identity module — the single source of truth.
The CLI's ops/identity.rs is now a thin CliError-mapping wrapper over it, and
dig-node loads the seed once and mints a fresh RequestIdentity per DigClient
via identity_from_seed. The signer is best-effort: with no identity key,
dig-node skips the authenticated sync and falls back to the per-resource proxy.
The synced module is not trusted at sync time — every response dig-node serves
from it carries its merkle proof, which the browser verifies against the
chain-anchored root.
TDD: dig-node is 8/8 (adds sync_eligible gating, verifiable-identity header
stamping against a mock §21 host, served-root cache keying, and the
no-identity skip path); digstore_remote::identity carries the seed/signer
tests ported from the CLI.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01HDr4m1MiYc5JPfjQ7Ed3fV
Implements the wallet's send/sign increment. digstore_chain::send builds + BLS- signs a standard XCH payment (AugScheme, drawing coins across the HD wallet): one lead coin carries the payment + change and reserves the fee, every other selected coin is spent under its own synthetic key bound to the lead via ASSERT_CONCURRENT_SPEND, so the bundle is atomic and balances exactly (inputs == amount + change + fee). Pure build + sign — it never broadcasts. dig-wallet exposes POST /api/send. Because a broadcast spends REAL mainnet funds, it is double-gated: it pushes only when the request sets broadcast:true AND the process runs with DIG_WALLET_ALLOW_BROADCAST=1; otherwise it returns the fully signed bundle as a dry run (status "signed") and pushes nothing. An explicit broadcast:true while disabled is refused (403), never silently downgraded — so the signing path is exercised unattended without spending. TDD: digstore-chain send 6/6 (balance invariant, multi-coin path, single-coin no-change, zero-amount + insufficient-funds errors, deterministic non-empty signing, and a conditions-decode proving the lead CREATE_COINs the recipient the exact amount); dig-wallet 2/2 on the broadcast safety gate. fmt + clippy -D warnings clean. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01HDr4m1MiYc5JPfjQ7Ed3fV
…/ pinning Adds a JSON-RPC method that resolves a store's CHIP-0035 chain-anchored tip root from coinset.org (via the already-tested digstore_chain::singleton::sync_datastore) — NEVER from the serving node. This is the trusted-root source for fixing the browser's fail-open dig:// verifier: a rootless dig:// URN must pin proof.root == anchored_root instead of trusting the rpc-served "latest" root. This is the verified Rust half of the fix; the thin C++ wiring in the DIG Browser (call dig.getAnchoredRoot for rootless URNs; drop the "latest" bypass in VerifyInclusion) is documented in the superproject HANDOFF.md and must be built + verified on Windows. TDD: dig-node 12/12 (adds store_id parsing + an invalid-params path that errors before any chain read); the resolution itself reuses sync_datastore's existing singleton tests. DIG_NODE_COINSET overrides the coinset base. fmt + clippy -D warnings clean. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01HDr4m1MiYc5JPfjQ7Ed3fV
MichaelTaylor3d
added a commit
that referenced
this pull request
Jun 27, 2026
Add `digstore deploy` + `digstore deploy-key export` and a composite GitHub Action so every push can publish a new capsule to an existing DIG store from CI — like Vercel's Git integration. CI advances the store (never mints: no `init`). Why a new command (not pure clone-glue): a fresh CI checkout has no `.dig`. `commit` needs `config.toml`, `anchor.toml`, `signing_key.bin` (the per-store BLS PUBLISHER key the DIGHub remote pinned at first push), and a `roots.log` head at the on-chain tip. `clone` re-keys with a FRESH host key and writes no `anchor.toml`, so a clone-then-push is rejected (wrong publisher key → 403). The publisher key is random at `init` and unrecoverable from the wallet seed — the one irreducible CI secret beyond the funded mnemonic. - `store_ops::adopt_existing_store`: reconstruct the per-store `.dig` from the provided publisher seed + the current on-chain root (read via `onchain_tip_root`); seeds anchor.toml=Confirmed@tip and roots.log head=tip so the next commit fast-forwards. `read_signing_seed` exports the key. - `digstore deploy`: reads a committable `dig.toml` (store-id, output-dir, build-command, remote, network, wait-timeout; flags/env override), optionally builds, adopts, stages output-dir, then runs the canonical `commit -m --push`. - `digstore deploy-key export`: print/write the 64-hex publisher seed for a CI secret (no spend authority). - Fix: `commit --push --json` now actually pushes. `--push` is built for CI (which runs `--json`), but the push only ran in the human branch — json+push silently published nothing. Shared `push::push_core` (no double-emitted JSON); json output gains `pushed`/`claimed`. Regression-tested. - action.yml (composite) + examples/ (workflow + dig.toml) + README section. Security: v1 ships the funded mnemonic as a CI secret — documented to use a dedicated low-balance deploy wallet; scoped revocable tokens are the planned Wave-2 replacement. TDD: 6 store_ops unit tests + 7 cli_deploy integration tests (incl. the core end-to-end proving a fresh checkout advances the store and the remote accepts the push with the original publisher key). Full suite green; guest wasm built, binary reinstalled, fmt + clippy(-D warnings) clean. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01GjQgGAisBupqs7vpkmUhuN
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three increments for the DIG Browser's native sidecars (all additive; no change to the digstore CLI command surface or the producer↔verifier contract):
1. dig-node — native Chia §21.9 identity signer + authenticated whole-store sync
On a local module-cache miss for a concrete
(store, root),dig-nodenow pulls the whole.digmodule from rpc.dig.net's auth-gated §21GET /stores/{id}/module, stampingX-Dig-Identity/-Timestamp/-Nonce/-Authexactly like the digstore CLI, caches it, and serves locally. The identity persistence + seed→BLS-key derivation +RequestIdentityconstruction live once in a shareddigstore_remote::identitymodule used by both the CLI (itsops/identity.rsis now a thin wrapper) and dig-node — no duplicated identity code. Best-effort: with no identity key it falls back to the anonymous proxy. Upstream rpc base overridable viaDIG_NODE_UPSTREAM.2. dig-wallet — native XCH send/sign (gated broadcast)
digstore_chain::sendbuilds + BLS-signs a standard XCH payment (AugScheme; lead-coin carries payment + change and reserves the fee, extra coins bound viaASSERT_CONCURRENT_SPEND; balances exactly). Pure build+sign — never broadcasts.POST /api/sendis double-gated: a real push needsbroadcast:trueandDIG_WALLET_ALLOW_BROADCAST=1; otherwise it returns the signed bundle as a dry run, and an explicit-but-disabled broadcast is refused (403).3. dig.getAnchoredRoot — trusted-root resolver (closes the fail-open dig:// verifier, Rust half)
dig-nodenow servesdig.getAnchoredRoot {store_id} → {root}, resolving a store's CHIP-0035 chain-anchored tip root from coinset.org via the already-testeddigstore_chain::singleton::sync_datastore— never from the serving node. This is the trusted-root source the browser must pin rootless URNs against (instead of the rpc-served"latest"root). The remaining thin C++ wiring in the DIG Browser is captured in the superprojectHANDOFF.md(it only builds on Windows).Tests
RemoteServeradmitting the native identity / rejecting anonymous, anchored-root input validation)send6/6 (balance invariant, multi-coin path, no-change, zero/insufficient errors, deterministic signing, conditions-decode proving the recipient is paid the exact amount)digstore_remote::identity2/2cargo fmt --all --check,cargo clippy --workspace --all-targets -- -D warnings, fulldigstore-chainlib suite (77) all green.Notes
ci.ymlbuild. A workspace version bump to0.5.29+ thev0.5.29release tag are the follow-up after merge (to cut the release binary viarelease.yml).SYSTEM.md/DEVELOPMENT_LOG.md/ runbooks updated in-tree (superproject) to match.🤖 Generated with Claude Code
https://claude.ai/code/session_01HDr4m1MiYc5JPfjQ7Ed3fV
Generated by Claude Code