DEV Community

Zeke
Zeke

Posted on

Chaintip freshness cert: signed identity scores that age with the chain

A schnorr signature tells you who. A timestamp tells you when. A chaintip tells you when, honestly. And a chaintip with a TTL tells you when and how long it's still good for. That last piece is what we shipped today on the Depth-of-Identity Oracle.

If you've been following the softwar thread (Lowery's Softwar, Paparo's INDOPACOM testimony, the Bitcoin Policy Institute's recent press cycle), the framing matters: bitcoin proof-of-work imposes a thermodynamic cost. A signature anchored to that cost gets weight that a wall-clock timestamp doesn't. We've been doing the binding side for a couple weeks (every signed DoI score envelope has carried bitcoin_tip {height, hash} since MR !171). What was missing: an expiration.

A signed score from yesterday still validated cryptographically today. The signature was fine. But "fine" is not what you want from an identity score. You want to know if it's current. So we added one field to the signed payload and one new endpoint:

{
  "pubkey": "...",
  "depth": { "social": 12, "access": 8, "vouch": 3, "economic": 21 },
  "composite": 44,
  "rank": "established",
  "bitcoin_tip": { "height": 946892, "hash": "0000...e0b3" },
  "freshness_blocks": 6,
  "signed_at": 1761579180,
  "valid_until": 1761582780,
  "signed_by": "b4b12dfb...",
  "signature": "<128-hex schnorr sig over canonical JSON>"
}
Enter fullscreen mode Exit fullscreen mode

freshness_blocks is now part of what the signature covers. Default 6, which is roughly 60 minutes on bitcoin. The verifier rejects scores where current_tip_height - bitcoin_tip.height > freshness_blocks. Replay an hour-old score against today's tip and it fails.

Why a window, not a wall-clock

Wall-clock TTL is the obvious choice, and it's wrong here. A wall-clock says "expires at 2:30pm." Whose 2:30pm? Whose clock? An attacker can lie about local time, and a verifier with a skewed clock reads the lie as truth.

A chaintip-block window says "expires 6 blocks past height N." That's a thermodynamic statement. To advance the chain by 6 blocks past height N, the bitcoin network has to actually mine 6 blocks. There's a real-world cost to that, distributed across miners globally, and no centralized clock to lie about. Either the chaintip is past the threshold or it isn't.

Same idea Lowery uses in Softwar for proof-of-work as a kinetic filter: we're substituting wall time (cheap to manipulate) for thermodynamic time (provably expensive to manipulate).

The verify endpoint

Two ways to check freshness. Server side: POST /oracle/freshness with the signed envelope and the current chaintip height. Get back:

{
  "valid_signature": true,
  "fresh": true,
  "current_tip_height": 946895,
  "signed_tip_height": 946892,
  "blocks_elapsed": 3,
  "freshness_blocks": 6,
  "fresh_until_height": 946898
}
Enter fullscreen mode Exit fullscreen mode

Client side: install @powforge/identity@0.7.1, call checkFreshness(scoreResponse, currentTipHeight), get the same envelope back without round-tripping the oracle. Pure function, signature must already be verified by the caller (either via the SDK's existing verify path or by hitting the oracle's /verify endpoint).

npm install @powforge/identity@0.7.1
Enter fullscreen mode Exit fullscreen mode
const { checkFreshness } = require('@powforge/identity');

const result = checkFreshness(signedScore, currentTipHeight);
if (!result.fresh) {
  // Re-fetch from /oracle/doi-score
}
Enter fullscreen mode Exit fullscreen mode

What this enables

The L402 invoice flow on pow-gate (and any other paid endpoint that prices by depth) now has a concrete expiration story. Cache a depth score for an hour, then refetch — that's not a heuristic, it's a contract you can prove. Long-running agents that hold credentials across sessions can verify their last score is still good without spending another sat. CDNs caching identity claims at the edge get a TTL that's bound to bitcoin time, not Cloudflare time.

For the broader thesis: every verifiable claim now ages with the chain. You can't replay yesterday's signed score against today's tip. The cost asymmetry that Softwar talks about — defender pays the engineering, attacker pays the power bill of a grandma in Ohio — gets a temporal floor too. The signature plus the chaintip plus the validity window is a one-shot proof that holds for exactly N blocks of real-world thermodynamic cost.

Try it

The oracle's manifest is public:

curl -s https://identity.powforge.dev/oracle/info | jq '.free_endpoints'
Enter fullscreen mode Exit fullscreen mode

You'll see /oracle/freshness listed as a free, public verify endpoint. Throw a base64-encoded signed score at it with a current tip height and watch the boolean come back.

Source: [powforge.dev SDK: npm @powforge/identity. Whitepaper: powforge.dev/whitepaper.

If you build something with it, tell me. Especially interested in the agent-credential-caching use case — that's where chaintip freshness pays for itself across sessions, and we don't have a paying customer there yet who can stress-test the assumption.

Zeke

Top comments (0)