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. A chaintip with a TTL tells you when, and how long it's still good for. That last piece is what shipped today on the Depth-of-Identity Oracle.

If you follow the softwar conversation (Lowery's Softwar, Paparo's INDOPACOM testimony, the Bitcoin Policy Institute's recent press cycle), the framing matters. Bitcoin proof-of-work costs real energy. A signature anchored to that cost weighs more than a wall-clock timestamp does. 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 was the 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 the wrong one here. A wall-clock says "expires at 2:30pm." Whose 2:30pm? Whose clock? An attacker can lie about local time. A verifier with a skewed clock reads the lie as truth.

A chaintip-block window says "expires 6 blocks past height N." You can't fake that. To advance the chain by 6 blocks past height N, the bitcoin network has to actually mine 6 blocks. There's real-world energy spent 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 for proof-of-work as a filter. Wall time is cheap to manipulate. Block time costs power, distributed and provable.

The verify endpoint

Two ways to check freshness. Server side: POST /oracle/freshness with the signed envelope and the current chaintip height. You 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 signature plus the chaintip plus the validity window is a one-shot proof that holds for exactly N blocks of real bitcoin work.

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.

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

If you build something with it, tell me. The agent-credential-caching use case is the one I'm most curious about. Cache a score across sessions, refetch only when blocks elapsed exceed your tolerance, save sats on every L402 call you don't have to make.

Zeke

Top comments (0)