Protocol · v0.0.1
Detection, verification, settlement.
Three separate stages. A flush is physically detected, an oracle decides whether to believe it, and only then can it be settled, in batches, on Solana.
Architecture
The pipeline
- 1
Device
ShitNode detects a flush and signs it with its ed25519 key.
- 2
Ingest
POST /api/telemetry receives the signed payload.
- 3
Oracle
Identity, signature, replay, timestamp, cooldown, rate limit.
- 4
Event store
Append-only record of every accept and reject.
- 5
Batcher
Groups 64 verified events and builds a Merkle root.
- 6
Solana
Optionally anchors the root. One tx per batch, not per flush.
- 7
Consumers
Points, leaderboards, receipts, the Degen Engine.
Telemetry
What a device sends
{
"v": 1,
"deviceId": "SN-PRO-00F3A1",
"counter": 18204,
"ts": 1793001234,
"event": {
"kind": "FLUSH",
"volumeL": 4.8,
"durationMs": 3120,
"flowProfile": "dual-low"
},
"fw": "0.0.1",
"sig": "base58-ed25519-signature"
}Each ShitNode has an ed25519 keypair generated inside a secure element. The private key never leaves the chip. The device signs the canonical JSON of everything except sig.
counter is a monotonic sequence held in the secure element. It only goes up, so a replayed payload is useless.
Try it locally: npm run device:sim signs fake events and posts them to /api/telemetry. That endpoint runs real signature, replay, cooldown and rate-limit checks.
Oracle
Trust, but verify the shit
Device authentication
The deviceId must be registered, with a known public key.
Signed payload
An ed25519 signature over the canonical JSON (everything except sig).
Replay detection
The counter must be strictly greater than the last one accepted for that device.
Timestamp check
The event time must be within ±120 s of server time.
Cooldown
At least 30 s between flushes per device, because tanks need time to refill.
Rate limit
No more than 10 flushes per device per hour, plus per-IP limits.
Idempotency
The same payload posted twice is a no-op and returns the original verdict.
Audit log
Every accept and reject is recorded with its reason.
Settlement
Why we batch
Writing every flush to Solana would be expensive and deeply unnecessary. Verified events are grouped into batches of 64, each event becomes a Merkle leaf, and only the root is anchored. Anyone holding a receipt can later prove their flush was in a batch. In simulation mode, nothing is sent and solanaTransaction stays null.
Threat model
Ways to cheat, and why they don't work
| Attack | Mitigation |
|---|---|
| Flushing an empty toilet over and over for points | Cooldown, hourly rate limit, a plausibility model on volume and duration, and shame. |
| Replaying a captured payload | Monotonic counter per device. Replays are rejected with REPLAY. |
| Forging events without hardware | No registered key means no valid signature. Rejected with BAD_SIG. |
| Clock games | A ±120 s skew window, rejected with CLOCK_SKEW. |
| Extracting the device key | The key lives in a secure element, can be revoked, and its oracle score drops. |
| Spamming the chain | There is no tx per event. Batches anchor a Merkle root, or anchoring is turned off entirely. |