Commit Graph

5 Commits

Author SHA1 Message Date
vsecoder
8082dd0bf7 fix(node): rate-limit relay HTTP endpoints
Relay routes were not wrapped in any guards — /relay/broadcast accepted
unlimited writes from any IP, and /relay/inbox could be scraped at line
rate. Combined with the per-recipient FIFO eviction (MailboxPerRecipientCap=500),
an unauthenticated attacker could wipe a victim's real messages by
spamming 500 garbage envelopes. This commit wraps writes in
withSubmitTxGuards (10/s per IP + 256 KiB body cap) and reads in
withReadLimit (20/s per IP) — the same limits already used for
/api/tx and /api/address.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 17:54:08 +03:00
vsecoder
32eec62ba4 fix(chain): RELAY_PROOF dedup by envelopeID + sticky BlockContact
RELAY_PROOF previously had no per-envelope dedup — every relay that
saw the gossipsub re-broadcast could extract the sender's FeeSig from
the envelope and submit its own RELAY_PROOF claim with its own
RelayPubKey. The tx-ID uniqueness check didn't help because tx.ID =
sha256(relayPubKey||envelopeID)[:16], which is unique per (relay,
envelope) pair. A malicious mesh of N relays could drain N× the fee
from the sender's balance for a single message.

Fix: record prefixRelayProof:<envelopeID> on first successful apply
and reject subsequent claims for the same envelope.

CONTACT_REQUEST previously overwrote any prior record (including a
blocked one) back to pending, letting spammers unblock themselves by
paying another MinContactFee. Now the handler reads the existing
record first and rejects the tx with "recipient has blocked sender"
when prev.Status == ContactBlocked. Block becomes sticky.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 17:51:14 +03:00
vsecoder
78d97281f0 fix(relay): canonicalise envelope ID and timestamp on mailbox.Store
The mailbox previously trusted the client-supplied envelope ID and SentAt,
which enabled two attacks:
  - replay via re-broadcast: a malicious relay could resubmit the same
    ciphertext under multiple IDs, causing the recipient to receive the
    same plaintext repeatedly;
  - timestamp spoofing: senders could back-date or future-date messages
    to bypass the 7-day TTL or fake chronology.

Store() now recomputes env.ID as hex(sha256(nonce||ct)[:16]) and
overwrites env.SentAt with time.Now().Unix(). Both values are mutated
on the envelope pointer so downstream gossipsub publishes agree on the
normalised form.

Also documents /relay/send as non-E2E — the endpoint seals with the
relay's own key, which breaks end-to-end authenticity. Clients wanting
real E2E should POST /relay/broadcast with a pre-sealed envelope.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
v1.0.1
2026-04-18 17:41:22 +03:00
vsecoder
546d2c503f chore(release): clean up repo for v0.0.1 release
Excluded from release bundle:
- CONTEXT.md, CHANGELOG.md (agent/project working notes)
- client-app/ (React Native messenger — tracked separately)
- contracts/hello_go/ (unused standalone example)

Kept contracts/counter/ and contracts/name_registry/ as vm-test fixtures
(referenced by vm/vm_test.go; NOT production contracts).

Docs refactor:
- docs/README.md — new top-level index with cross-references
- docs/quickstart.md — rewrite around single-node as primary path
- docs/node/README.md — full rewrite, all CLI flags, schema table
- docs/api/README.md — add /api/well-known-version, /api/update-check
- docs/contracts/README.md — split native (Go) vs WASM (user-deployable)
- docs/update-system.md — new, full 5-layer update system design
- README.md — link into docs/, drop CHANGELOG/client-app references

Build-time version system (inherited from earlier commits this branch):
- node --version / client --version with ldflags-injected metadata
- /api/well-known-version with {build, protocol_version, features[]}
- Peer-version gossip on dchain/version/v1
- /api/update-check against Gitea release API
- deploy/single/update.sh with semver guard + 15-min systemd jitter
v0.0.1
2026-04-17 14:37:00 +03:00
vsecoder
7e7393e4f8 chore: initial commit for v0.0.1
DChain single-node blockchain + React Native messenger client.

Core:
- PBFT consensus with multi-sig validator admission + equivocation slashing
- BadgerDB + schema migration scaffold (CurrentSchemaVersion=0)
- libp2p gossipsub (tx/v1, blocks/v1, relay/v1, version/v1)
- Native Go contracts (username_registry) alongside WASM (wazero)
- WebSocket gateway with topic-based fanout + Ed25519-nonce auth
- Relay mailbox with NaCl envelope encryption (X25519 + Ed25519)
- Prometheus /metrics, per-IP rate limit, body-size cap

Deployment:
- Single-node compose (deploy/single/) with Caddy TLS + optional Prometheus
- 3-node dev compose (docker-compose.yml) with mocked internet topology
- 3-validator prod compose (deploy/prod/) for federation
- Auto-update from Gitea via /api/update-check + systemd timer
- Build-time version injection (ldflags → node --version)
- UI / Swagger toggle flags (DCHAIN_DISABLE_UI, DCHAIN_DISABLE_SWAGGER)

Client (client-app/):
- Expo / React Native / NativeWind
- E2E NaCl encryption, typing indicator, contact requests
- Auto-discovery of canonical contracts, chain_id aware, WS reconnect on node switch

Documentation:
- README.md, CHANGELOG.md, CONTEXT.md
- deploy/single/README.md with 6 operator scenarios
- deploy/UPDATE_STRATEGY.md with 4-layer forward-compat design
- docs/contracts/*.md per contract
2026-04-17 14:16:44 +03:00