跳转至主要内容

Service Challenge Integration

Practical guide to integrating MatMul service challenges for API rate limiting, spam prevention, and AI endpoint gating.

开发上下文

这份参考属于 BTX 构建者部署路径的一部分。

回到 Develop 微站,可以把这页重新放回 AI 代理 CAPTCHA、后量子身份和开发启动包的完整叙事中理解。

This guide walks through integrating BTX MatMul service challenges into your application. Service challenges let you require computational proof-of-work from clients before admitting requests — useful for API rate limiting, signup spam prevention, and AI inference endpoint gating.

For the RPC reference, see Service Challenge RPCs.


Architecture

The service challenge flow involves three participants: your application server, a BTX node, and the client.

┌──────────┐    1. Issue challenge     ┌──────────┐
│          │ ──────────────────────── ▶ │          │
│  Your    │    (getmatmulservice       │  BTX     │
│  App     │     challenge)             │  Node    │
│  Server  │                            │  :19334  │
│          │ ◀ ──────────────────────── │          │
│          │    challenge envelope       │          │
└────┬─────┘                            └────┬─────┘
     │                                       │
     │  2. Send envelope to client           │
     ▼                                       │
┌──────────┐                                 │
│  Client  │    3. Solve MatMul puzzle       │
│          │       (local computation)       │
└────┬─────┘                                 │
     │                                       │
     │  4. Return proof (nonce + digest)     │
     ▼                                       │
┌──────────┐    5. Redeem proof         ┌────┴─────┐
│  Your    │ ──────────────────────── ▶ │  BTX     │
│  App     │    (redeemmatmulservice    │  Node    │
│  Server  │     proof)                 │          │
│          │ ◀ ──────────────────────── │          │
│          │    valid/redeemed/reason    │          │
└──────────┘                            └──────────┘

Key properties of this flow:

  • Each challenge is one-shot — once redeemed, replay returns already_redeemed
  • Challenges are domain-bound to a purpose, resource, and subject
  • Work is anchored to current chain state, so pre-computation is time-limited
  • Verification is cheap relative to the solve cost

The Core Flow

Step 1: Issue a Challenge

Call getmatmulservicechallenge with bindings for your use case:

curl --silent --user "$BTX_RPC_USER:$BTX_RPC_PASSWORD" \
  --data-binary '{
    "jsonrpc":"1.0",
    "id":"issue",
    "method":"getmatmulservicechallenge",
    "params":["rate_limit","signup:/v1/messages","user:[email protected]",2,300,0.25,0.75]
  }' \
  -H 'content-type: text/plain;' \
  http://127.0.0.1:19334/

The parameters are:

PositionNameDescription
1purposeChallenge domain: rate_limit, api_gate, ai_inference_gate
2resourceThe protected resource, e.g. signup:/v1/messages
3subjectThe requester identity, e.g. user:[email protected] or ip:203.0.113.5
4target_solve_time_sTarget solve time in seconds (difficulty calibration)
5expiry_sChallenge validity window in seconds
6min_difficulty_factorMinimum difficulty relative to network (0.0-1.0)
7max_difficulty_factorMaximum difficulty relative to network (0.0-1.0)

The response contains a challenge envelope with:

  • challenge_id — unique identifier for replay protection
  • issued_at / expires_at — validity window
  • header_context — chain-anchored header for deterministic seeds
  • target — difficulty target the client must meet
  • MatMul seeds derived from the challenge_id

Step 2: Client Solves the Challenge

Send the challenge envelope to the client. The client performs the MatMul computation locally — multiplying matrices, hashing the result, and searching for a nonce whose digest meets the target. The output is a nonce64_hex and digest_hex.

Step 3: Redeem the Proof

When the client returns the proof, call redeemmatmulserviceproof:

curl --silent --user "$BTX_RPC_USER:$BTX_RPC_PASSWORD" \
  --data-binary '{
    "jsonrpc":"1.0",
    "id":"redeem",
    "method":"redeemmatmulserviceproof",
    "params":[CHALLENGE_ENVELOPE,"0000000000000001","DIGEST_HEX"]
  }' \
  -H 'content-type: text/plain;' \
  http://127.0.0.1:19334/

Accept the request only when all three conditions hold:

  • valid = true
  • reason = "ok"
  • redeemed = true

Integration Patterns

Signup and Comment Spam Prevention

Require proof-of-work before accepting form submissions. This raises the cost of automated spam without blocking legitimate users.

BindingRecommended Value
purposerate_limit
resourcesignup:/v1/messages or comment:/v1/posts/:id
subjectuser:<id> or ip:<bucket>
expiry60-300 seconds
target_solve_time_s1-3 seconds (high enough to price abuse, low enough for UX)

Issue the challenge on form render or just before submission. Redeem on final submit, not on initial page load.

API Rate Limiting

Gate public API endpoints behind proof-of-work instead of (or alongside) API key quotas.

BindingRecommended Value
purposeapi_gate
resourcePOST:/v1/inference or GET:/v1/search
subjectapi_key:<id> or tenant:<id>

Use shorter expiries and redeem on request receipt so stale pre-computation is less useful.

AI Inference Endpoint Gating

Protect expensive AI model endpoints by requiring useful work before inference is admitted. This is effective for free-tier throttling, anonymous endpoint hardening, and protecting multimodal routes.

BindingRecommended Value
purposeai_inference_gate
resourcemodel:gpt-x|route:/v1/generate|tier:free
subjecttenant:abc123

Scale puzzle cost by endpoint sensitivity, user trust level, or tenant risk score using getmatmulservicechallengeprofile to calibrate difficulty for a specific target solve time.


Reference Architectures

Develop 微站把 service challenge 的接入方式归纳为几种常见的路由形态。你可以把它们当作起始契约,再根据真实求解延迟、滥用类型和自身集群拓扑继续调优。

Profile: Public AI Inference API

Use this when the expensive thing is model execution itself and you want a machine-readable work gate in front of a free-tier or lightly trusted route.

BindingRecommended value
purposeai_inference_gate
resourcemodel:gpt-x|route:/v1/generate|tier:free
subjecttenant:<id> or api_key:<id>
target_solve_time_s2-4 seconds for free-tier or anonymous traffic
expiry_s60-180 seconds so old envelopes lose value quickly
Redeem pathStart with redeemmatmulserviceproof at the front door, then move to redeemmatmulserviceproofs only when queued or shared-worker inference benefits from batching

Issue the challenge before the request enters the expensive queue, persist challenge_id beside the upstream request id, and only add batch redemption when your worker pool actually benefits from it. Pair this profile with difficulty calibration as route cost or tenant risk changes.

Profile: Agent or Tool Gateway

Use this when a signed caller is already presenting a wallet identity, device token, or route scope and you want fresh work to guard the expensive or privileged action behind that gateway.

BindingRecommended value
purposeapi_gate
resourcetool:calendar.write|route:/mcp/tools/calendar.write
subjectwallet:agent-42 or device:devtok_abc123
target_solve_time_s1-2 seconds for interactive calls, higher for privileged routes
expiry_s30-120 seconds so the signature and work remain tightly coupled
Redeem pathUse redeemmatmulserviceproof at the gateway edge for one request at a time

Keep the resource specific to the exact tool or route. Do not let a generic gateway proof float across unrelated capabilities. This profile maps cleanly onto stacks that already track role, scope, and device trust, so pair it with the protected route contract and its header semantics.

Profile: Anonymous Public Submission

Use this when you need friction for signup, comments, intake forms, or other open routes where the caller may have no durable account yet.

BindingRecommended value
purposerate_limit
resourcesignup:/v1/messages or comment:/v1/posts/:id
subjectip:203.0.113.0/24 or user:[email protected]
target_solve_time_s1-3 seconds so honest users can finish while spam cost rises materially
expiry_s60-300 seconds, with redemption only on the final submit
Redeem pathUse redeemmatmulserviceproof on final submit unless accepted work is later batched for moderation or ingestion

Start from the core flow and issue the challenge just before submission or alongside short-lived draft state. Avoid burning proofs on read-only page views, and if accepted work later fans into queues preserve the original redeem result instead of trying to replay the same proof downstream.

Batch Redemption

High-throughput gateways should use redeemmatmulserviceproofs to redeem multiple proofs in a single RPC round trip:

curl --silent --user "$BTX_RPC_USER:$BTX_RPC_PASSWORD" \
  --data-binary '{
    "jsonrpc":"1.0",
    "id":"redeem-batch",
    "method":"redeemmatmulserviceproofs",
    "params":[[
      {
        "challenge": "CHALLENGE_A",
        "nonce64_hex": "0000000000000001",
        "digest_hex": "DIGEST_A"
      },
      {
        "challenge": "CHALLENGE_B",
        "nonce64_hex": "0000000000000002",
        "digest_hex": "DIGEST_B"
      }
    ]]
  }' \
  -H 'content-type: text/plain;' \
  http://127.0.0.1:19334/

Batch semantics:

  • Processing order is preserved
  • The operation is sequential, not all-or-nothing
  • Duplicate or already-redeemed proofs return already_redeemed
  • Unknown cross-node challenges return unknown_challenge

The response includes count, valid, invalid, by_reason, and ordered per-item results.


Difficulty Calibration

Use getmatmulservicechallengeprofile to get a challenge shape for a custom solve-time target. This lets you dynamically price work based on:

  • Endpoint sensitivity (a public comments form vs. a free-tier AI image endpoint)
  • User trust level (verified accounts get easier puzzles)
  • Tenant risk score
  • Live network conditions (via getdifficultyhealth)

Example: a public comments endpoint might target 1 second of solve time, while a free-tier AI image generation route might target 4 seconds.


Protected Route Contract

Once you move beyond the primitives, treat BTX as a first-party contract between your edge or gateway layer and the issuing BTX node. The goal is a deterministic request lifecycle: issue, solve, redeem, admit or reject.

Issue Contract

PhaseExpectationOperator Note
Issue Call getmatmulservicechallenge using route-specific purpose, resource, and subject bindings. Do this at the edge or on the first admission hop, not deep inside the expensive handler.
Return envelope Return challenge_id, expires_at, target, and the chain-bound envelope to the caller. Persist the issuing-node identity beside the envelope if your fleet has more than one BTX node.
Redeem Redeem on the same node that issued the challenge unless you have a shared challenge store. This is the operational reason sticky routing matters in multi-node setups.

Protected-Route Headers

The exact transport is up to your gateway, but this is the recommended BTX-owned contract for protected HTTP routes:

HeaderRequiredPurpose
AuthorizationOptional but recommendedCaller signature, bearer token, or gateway auth material that identifies who is asking for service.
X-Device-TokenOptionalGateway or device-trust token when your stack already distinguishes device posture from caller identity.
X-BTX-Challenge-IdRequiredThe challenge envelope identifier that lets the gateway and BTX node resolve the live challenge state.
X-BTX-Proof-NonceRequiredThe client-solved nonce64_hex value returned by the local MatMul solve.
X-BTX-Proof-DigestRequiredThe resulting digest_hex that is checked against the challenge target on redeem.

Failure Semantics

ConditionWhat it meansRecommended action
missing_proof The caller reached a protected route without the BTX proof headers. Reject immediately and return a fresh issue path or challenge envelope.
unknown_challenge The redeeming node does not know the challenge, usually because of sticky routing drift or a node restart. Reissue from the current node and inspect sticky routing before retrying expensive routes.
already_redeemed The challenge was already consumed, which usually means replay or double-submit behavior. Reject as a replay attempt; do not auto-reissue on the same request.
expired or past expires_at The caller solved too slowly or the envelope sat in a queue too long. Reject, issue a new challenge, and reconsider expiry_s or the target solve time for that route.
valid = false or reason != "ok" The proof does not satisfy the current challenge or target. Reject the request and only reissue if the user experience genuinely benefits from another attempt.

Route Tuning

Route classtarget_solve_time_sexpiry_sDifficulty band
Public signup or comments1-260-1200.15-0.45
Anonymous search or text API2-360-1800.20-0.60
Free-tier AI inference2-4120-3000.25-0.75
Expensive multimodal or batch work4-8180-3000.35-0.90

Use getmatmulservicechallengeprofile and getdifficultyhealth together when tuning these values. The correct answer depends on both route cost and current network conditions.

Monitoring Checklist

  • Track getdifficultyhealth before changing solve targets so you are not tuning against a blind difficulty view.
  • Alert on spikes in unknown_challenge; they usually indicate sticky routing failures or node restarts.
  • Alert on rising already_redeemed rates; they often indicate replay or duplicate-submit patterns.
  • Watch expiry rate and median solve duration together. If honest callers are expiring, loosen expiry_s or lower route cost.

Deployment Considerations

Single-Node Deployment

The simplest deployment runs issuance and redemption on the same BTX node:

  • Issue with getmatmulservicechallenge
  • Redeem on the same node with redeemmatmulserviceproof
  • Issued challenge state lives in the node's local persistent registry by default
  • The default registry path is matmul_service_challenges.dat under the network datadir
  • Restarts preserve outstanding challenge state as long as that registry remains available

This is production-ready for most use cases.

Multi-Node Deployment

The redeem path still depends on the configured issued-challenge registry. This means:

  • Cross-node redemption is rejected as unknown_challenge when nodes do not share registry state
  • Horizontally scaled frontends still need sticky routing unless nodes share the same registry file
  • You can point multiple BTX nodes at the same -matmulservicechallengefile=<file> path to share issuance and redemption state

For production multi-node deployments, either keep session affinity in front of node-local registries or configure a shared challenge registry file across the service nodes that issue and redeem proofs.


Verify vs. Redeem

BTX provides two verification paths:

RPCReplay Safe?Use When
verifymatmulserviceproofNoDiagnostics, offline checking, debugging
redeemmatmulserviceproofYesProduction admission control

Always use redeem for real admission control. Stateless verify alone does not prevent replay.


What BTX Does and Does Not Prove

BTX proves that useful matrix-multiplication work was performed against a BTX-defined challenge and that the resulting digest met the required target.

BTX does not prove that:

  • A specific AI model produced a specific output
  • A claimed inference trace was faithful
  • An application request should be authorized for business reasons

For semantic proof-of-inference, pair BTX admission control with a verifiable inference layer such as Jolt Atlas, EZKL, or RISC Zero.


Comparison with Other Defenses

MechanismProves WorkCheap to VerifyReusable for AI InfraGood for Spam
BTX service challengeYesYesYesYes
Hashcash-style hash puzzleYesYesNoYes
CAPTCHANoN/ANoSometimes
API key / auth onlyNoYesN/AWeak
Verifiable inference layerExecution onlyExpensiveSometimesIndirectly