Service Challenge Integration
Practical guide to integrating MatMul service challenges for API rate limiting, spam prevention, and AI endpoint gating.
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:alice@example.com",2,300,0.25,0.75]
}' \
-H 'content-type: text/plain;' \
http://127.0.0.1:19334/ The parameters are:
| Position | Name | Description |
|---|---|---|
| 1 | purpose | Challenge domain: rate_limit, api_gate, ai_inference_gate |
| 2 | resource | The protected resource, e.g. signup:/v1/messages |
| 3 | subject | The requester identity, e.g. user:alice@example.com or ip:203.0.113.5 |
| 4 | target_solve_time_s | Target solve time in seconds (difficulty calibration) |
| 5 | expiry_s | Challenge validity window in seconds |
| 6 | min_difficulty_factor | Minimum difficulty relative to network (0.0-1.0) |
| 7 | max_difficulty_factor | Maximum difficulty relative to network (0.0-1.0) |
The response contains a challenge envelope with:
challenge_id— unique identifier for replay protectionissued_at/expires_at— validity windowheader_context— chain-anchored header for deterministic seedstarget— 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 = truereason = "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.
| Binding | Recommended Value |
|---|---|
purpose | rate_limit |
resource | signup:/v1/messages or comment:/v1/posts/:id |
subject | user:<id> or ip:<bucket> |
expiry | 60-300 seconds |
target_solve_time_s | 1-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.
| Binding | Recommended Value |
|---|---|
purpose | api_gate |
resource | POST:/v1/inference or GET:/v1/search |
subject | api_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.
| Binding | Recommended Value |
|---|---|
purpose | ai_inference_gate |
resource | model:gpt-x|route:/v1/generate|tier:free |
subject | tenant:abc123 |
Scale puzzle cost by endpoint sensitivity, user trust level, or tenant risk score using getmatmulchallengeprofile to calibrate difficulty for a specific target solve time.
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 getmatmulchallengeprofile 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.
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 - Challenge state lives in the node's local process memory
- Capacity: 10,000 active issued challenges per node
This is production-ready for most use cases.
Multi-Node Deployment
The issued-challenge store is currently local process memory only. This means:
- Daemon restarts clear outstanding challenge state
- Cross-node redemption is rejected as
unknown_challenge - Horizontally scaled frontends need sticky routing to ensure redemption hits the issuing node
For production multi-node deployments, route requests with session affinity or deploy a shared challenge store layer in front of multiple BTX nodes.
Verify vs. Redeem
BTX provides two verification paths:
| RPC | Replay Safe? | Use When |
|---|---|---|
verifymatmulserviceproof | No | Diagnostics, offline checking, debugging |
redeemmatmulserviceproof | Yes | Production 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
| Mechanism | Proves Work | Cheap to Verify | Reusable for AI Infra | Good for Spam |
|---|---|---|---|---|
| BTX service challenge | Yes | Yes | Yes | Yes |
| Hashcash-style hash puzzle | Yes | Yes | No | Yes |
| CAPTCHA | No | N/A | No | Sometimes |
| API key / auth only | No | Yes | N/A | Weak |
| Verifiable inference layer | Execution only | Expensive | Sometimes | Indirectly |