Skip to content

feat(depin-attest): T1 Solana DePIN attestation plugin with durable-nonce replay guard#107

Open
Emran-goat wants to merge 1 commit into
zeroclaw-labs:mainfrom
Emran-goat:feat/depin-attest
Open

feat(depin-attest): T1 Solana DePIN attestation plugin with durable-nonce replay guard#107
Emran-goat wants to merge 1 commit into
zeroclaw-labs:mainfrom
Emran-goat:feat/depin-attest

Conversation

@Emran-goat

Copy link
Copy Markdown

Summary

Adds depin-attest, a read-only T1 tool plugin that builds unsigned Solana versioned transactions committing a DePIN device attestation on-chain via a memo instruction with a durable-nonce advance as replay guard.

Track C (DePIN & the physical edge) — the bounty's stated favorite.

What it does

The agent calls depin_attest with a device identifier, a sensor reading (kind, value, timestamp, device signature), and a monotonic nonce counter. The plugin:

  1. Validates config (rpc_url, device_id, nonce_account, nonce_authority)
  2. Replay guard: rejects if nonce_counter <= last_committed_counter
  3. Clock skew guard: rejects if |now - ts| > 300s
  4. Fetches recent blockhash via Solana RPC
  5. Builds a versioned transaction with [advance-nonce, memo] instructions
  6. Returns base64 + a human-readable summary (~20 tokens)
  7. Human or Squads multisig signs externally

Key design decisions

  • Durable nonce solves Trap Self-contained WIT plugin registry + example plugins (wikipedia-summary, mastodon-post) #1 (blockhash expiry) — the bounty explicitly calls this out
  • No solana-sdk — hand-encoded Solana message v0 format, base58 constants, zero wasm friction
  • T1 custody — no signing, no secret keys, no private key in config. The plugin is a transaction builder, not a wallet
  • Pure core / thin shimcore.rs has zero wasm deps, tests run with plain cargo test
  • Nonce account is NOT a signer — only the nonce authority signs; nonce_account is readonly unsigned (verified in code review)

Test results

running 13 tests (lib) — all passed
running 16 tests (integration) — all passed
cargo build --target wasm32-wasip2 — clean (363 KB component)

Tests cover: happy path, nonce replay, counter regression, clock skew (old/future/zero), RPC failure, missing config, memo overflow, prompt injection (2 cases), base64 decodability, cold-start guard.

Custody tier: T1 (Build)

Returns unsigned transaction. No signing, no secret keys. The human always signs. T0 is too limited for real DePIN flows; T2 carries unacceptable prompt-injection risk for a reference implementation.

Threat model (8 threats, each with named error variant)

Threat Defense
Prompt injection: change device_id Summary shows device_id, human rejects
Nonce replay AttestError::NonceReplay — strict advance required
Clock skew AttestError::TsSkew — 5min max
Memo overflow AttestError::MemoTooLarge — 1024 byte limit
RPC failure AttestError::RpcError — never panics
Missing config AttestError::MissingRpcUrl/NonceAccount
Device key compromise Advisory at T1, human verifies
Nonce account drained Operator controls nonce_authority

Prompt-injection transcript

See README.md — two scenarios: (a) counter advances → tx built, summary reveals attack, human rejects; (b) counter already maxed → NonceReplay rejected.

Permissions

["http_client", "config_read"] — minimal. Only outbound HTTPS to Solana RPC and read access to own config section.

What's next

  • Verify ed25519 device signature in-plugin (when crypto capability ships)
  • Read on-chain nonce account state directly (instead of config-tracked counter)
  • Support sensor WIT capability for real GPIO/I2C/SPI reads

Build

rustup target add wasm32-wasip2
cargo build --target wasm32-wasip2 --release

Superteam Earn submission: depin-attest (Track C, T1)
Building in public: updates on X during the bounty period

…once replay guard

Adds depin-attest, a read-only T1 tool plugin that builds unsigned Solana
versioned transactions committing a DePIN device attestation on-chain via a
memo instruction with a durable-nonce advance as replay guard.

Track C (DePIN & physical edge) submission for Superteam Brasil bounty.

- Pure core (no wasm deps): hand-encoded Solana message v0, base58, borsh-free
- Wasm shim: WIT tool-plugin world, WasmRpc over waki, structured logging
- 29 host tests (13 lib + 16 integration), all mocked RPC, no live network
- wasm32-wasip2 release build clean (363 KB component)
- Custody T1: no signing, no secret keys, no private key in config
- Fail-closed: replay guard, clock skew, memo overflow, missing config
- Prompt-injection transcript in README
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant