Grant Application (community review): Ironwood Sentinel - Conformance and Readiness Testing for Zcash Wallets and Infrastructure

Posting my ZCG grant application here for community review, as required. Feedback and criticism welcome.

GitHub application: Grant Application - Ironwood Sentinel · Issue #376 · ZcashCommunityGrants/zcashcommunitygrants · GitHub

Repo: GitHub - DanielDerefaka/ironwood-sentinel: Readiness and conformance checks for Zcash infrastructure in the Ironwood (NU6.3) era · GitHub

I built a tool that tests whether Zcash infrastructure is actually ready for Ironwood not just “up”, but whether a server is really serving the Ironwood commitment tree, on the right consensus branch (37a5165b), at a version that meets the activation floor. It’s activation aware: before the NU6.3 height it reports “not applicable” rather than a false failure.

I ran it across the five public zec.rocks endpoints live through the July 28 activation. It caught the branch flip (5437f330 → 37a5165b) and the mainnet Ironwood pool two blocks into existence, with four notes in its tree. It also flagged that the old default endpoint mainnet.lightwalletd.com no longer resolves in DNS, though wallet configs still point to it. Before/after report with raw JSON is in the repo.

The grant extends this into the two layers above endpoints:

- A wallet behavioral suite - receive, spend, change, reorg, restore, and interrupted-migration recovery on regtest with the core test work merged upstream into librustzcash. I’ve claimed the open issue #2617 (running the shared ShieldedPoolTester suite with Ironwood as the active pool).

- A ZIP 318 migration linter - checks a wallet’s migration plan against the privacy recommendations: canonical denominations, residual caps, anchor-height buckets, and warnings on distinctive amounts that fingerprint users during the turnstile crossing.

$27,000, Security, 6 months startup $3k plus three $8k milestones. Full user stories, deliverables, and acceptance criteria are in the GitHub issue. If it isn’t funded, the tool stays open source and the endpoint monitor keeps running; funding changes the speed, not the direction.

@emersonian I scanned the zec.rocks endpoints through activation and they all crossed cleanly; since you maintain the readiness list by hand, I’d value your take on whether this is useful for keeping it current.

@zancas given the zaino/zingolib side of the migration and #2617, I’d welcome your feedback on the behavioral suite scope.

Happy to answer questions here. cc @ZcashGrants

2 Likes

One case that may be worth covering is wallets relying on managed RPC or Blockbook providers. We can confirm the synced height and Ironwood branch ID from a public status response, but some services expose the backend only as version: "zebra" or restrict RPC methods that reveal the exact build.

Would Sentinel distinguish between “consensus-ready” and “backend version unverified,” rather than treating readiness as a single pass/fail result? A machine-readable distinction like that could help wallet teams avoid overclaiming compatibility.

1 Like

Good question, and that’s the right split.

The checks already fall into two groups, the output just doesn’t label them well enough yet.
Directly observed: the branch ID, whether the Ironwood commitment tree is actually being served (GetLatestTreeState), and the Ironwood compact block metadata. A proxy can’t fake those without really serving Ironwood data, so they hold up no matter what the backend claims to be.

Self reported: the vendor and version strings from GetLightdInfo. That’s a claim, not proof, and managed providers are exactly where it falls apart.

So yes, those should be separate verdicts instead of one score. Unknown vendors already warn rather than fail, but the overall percentage and the exit code flatten it, which is the overclaiming risk you’re describing.

Your case also turned up a bug I just confirmed. If a provider reports vendor “zebra” with an opaque or missing version, the version floor check matches the zebra entry, can’t parse a version, and reports below floor. So it says the backend is outdated when the honest answer is it’s unverifiable. That’s a false failure in exactly the setup you mentioned, thanks for catching it.

Shape I’m planning:

```json

“consensus”: {

“verdict”: “ready”,

“evidence”: “observed”,

“branch_id”: “37a5165b”,

“ironwood_tree”: “served”

},

“backend_provenance”: {

“verdict”: “unverified”,

“evidence”: “self-reported”,

“vendor”: “zebra”,

“version”: null,

“reason”: “no build detail exposed by provider”

}

```

unverified becomes its own value separate from fail, and the exit code only keys off consensus, so a managed endpoint that’s genuinely serving Ironwood doesn’t get flagged as broken just because its build isn’t inspectable.

Does that fit how Gem Wallet would use it? If there are other provider shapes worth covering, Blockbook style responses or restricted RPC sets, I’d rather build against real ones than guess.

1 Like

Yes, that separation fits our use case well.

Gem’s public endpoint is a concrete Blockbook-style example:

https://gemnodes.com/zcash/api/

It exposes inSync, matching block/header heights, backend.version: "zebra", and the consensus branch ID, but no semantic build or subversion. Access to some upstream provider RPC methods may also be restricted.

One nuance is that Gem currently supports transparent ZEC only, so GetLatestTreeState and Ironwood compact-block metadata are not part of this interface or evidence of our wallet’s current capabilities. Capability-scoped results could make the distinction clearer:

  • transparent_consensus: ready
  • shielded_endpoint: not evaluated or unsupported
  • backend_provenance: unverified

We also confirmed a successful transparent transaction after activation. That combination would accurately describe what we can verify without implying shielded or migration readiness.

The proposed unverified verdict for an opaque Zebra version looks right to me.

1 Like

Thanks, that endpoint is a great test case. I ran it against the current tip and it matches what you described:

```

chain main

consensus.chaintip 37a5165b (nextblock agrees)

blocks == headers true

inSync true

backend.version “zebra” (no build or subversion)

```

There’s one thing I want to pull apart, because it changes how I’d label it. The branch ID is still something the backend tells us, so by itself it’s a claim, same as the version string. What makes it stronger here is that the tip can be checked: I compared bestBlockHash at that height against an independent source and it matched exactly. A backend on a different consensus branch would have forked and wouldn’t agree on the tip. So the branch ID is corroborated, not just asserted, and that holds even with an opaque build.

I’d rather build that in than paper over it. Self-reported, corroborated and observed are three different levels of confidence, and the Blockbook shape can reach corroborated on consensus while staying unverified on provenance.

Capability scoping makes sense to me and I’ll take it. Splitting it out means the missing shielded checks read as out of scope for the interface rather than a gap. For this endpoint that gives:

```json

“consensus”: {

“verdict”: “ready”,

“evidence”: “corroborated”,

“branch_id”: “37a5165b”,

“corroborated_by”: “tip hash matches independent source”

},

“capabilities”: {

“transparent”: “supported”,

“shielded”: “not_exposed_by_interface”

},

“backend_provenance”: {

“verdict”: “unverified”,

“evidence”: “self-reported”,

“backend”: “zebra”,

“version”: null,

“reason”: “no build or subversion exposed”

}

```

I’ve gone with not_exposed_by_interface rather than not_supported, because those say different things. One is about what this endpoint serves, the other is about your wallet, and Sentinel can only really speak to the first. If that distinction matters for how you’d want to display it, let me know and I’ll change the wording.

I’ll add gemnodes as a Blockbook fixture so this shape stays covered as things change. Glad the unverified verdict reads right to you.

1 Like

I’m finding it difficult to understand what’s the value on this grant.

This is something that I just did with Claude without knowing the existence of this proposal and it gave me a point by point analysis of a wallet’s conformance to ZIP-318

1 Like

you’re right that an LLM can read ZIP-318 and give you a point by point analysis. That’s genuinely useful and it does change what the analysis part is worth.

The difference is that your run was a one time read by someone who knew what to ask. Three things it doesn’t give you:

It won’t run again, so it won’t catch the regression someone adds next month.

It reads the code instead of executing it. Denominations and residuals you can reason about from source. What happens when a migration is interrupted and restarted, or a reorg lands on a migration transaction, or a wallet restores from seed with partially migrated funds, you have to actually trigger. That’s the regtest layer and I’d say it’s the real work here.

It isn’t comparable across wallets. One analysis in prose is a snapshot. The same checks run against every wallet give you results you can line up side by side.

There’s also a layer you can’t analyse at all. Whether a live endpoint is actually serving the Ironwood commitment tree needs a network call. That part already works, and it already found a dead default endpoint that wallet configs still point at, plus a false failure in my own version check that Gem Wallet’s question surfaced.

I’ll take the point on the linter though. If a model can enumerate the rules in one shot then encoding them is cheaper than I budgeted.

Easiest way to settle it is by letting me point it at ZODL and you compare. If it finds nothing your analysis didn’t, that’s a real answer and worth saying publicly.

I agree that it’s important that users can have some assurances that wallets they trust actually implement ZIP-318. I appreciate the effort and your concerns. Although, I don’t agree with some of your points.

not a problem. We could set that up.

This is not necessarily true. AI can do deep analysis of codepaths as static analysis can plus add other dynamics in the mix.

Regtest support is not widespread and uniform across the ecosystem. This is an actual contribution that goes beyond Ironwood migration.

Also arguable. This can also be set.

Yes but the effort is quite negligible.

Much welcome. You don’t need permission. ZODL is open source so you can already do this. :smiling_face_with_three_hearts: Scrutiny is very important and appreciated.

Going back to the grant itself, the timeline extends too much in time. IIUC, wallet developers would have the conformance tool in 4 months and regressions for January 2027. Is that correct?

2 Likes

Thanks, and I think you’ve found the part that actually matters.

On regtest, agreed, and I’d rather build the proposal around that than around Ironwood. Uneven regtest support is what makes everything else awkward to test, and it outlives this migration

On the timeline, your reading was right and the ordering was wrong. Tooling at month four is no help for a migration happening now. I had the upstream test work first and the thing wallet devs actually run later, which is backwards.

The regtest harness and the ZIP-318 checks come first, runnable against your own build in about six weeks rather than month four, with CI packaging and the wider wallet coverage after that, so regressions are running by late October instead of January. The upgrade parameterising and docs move to the end where they belong. I can pull it forward because the endpoint checks are already built, so it isn’t from scratch. I’ll update the application with the revised milestones.

On “we could set that up”, you’re right, any team can. The case for funding is that it gets built once and everyone gets it, instead of five teams wiring up five setups that don’t compare. If that’s not grant worthy then fine, but that’s the argument rather than it being hard.

And taking you up on ZODL. I’ll run what exists against it and post results here, including whatever it misses, since that’s the part that tells you if this is worth anything.

Thank you for submitting your proposal. Following a thorough review by the ZCG and a period for community feedback on the forum, the committee has decided not to move forward with this proposal.

We sincerely appreciate the time and effort you invested in your application and encourage you to stay involved and continue contributing to the Zcash community.

Meeting Minutes