Files
dchain/docs/contracts/username_registry.md
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

134 lines
5.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# username_registry
Привязка читаемых `@username` к адресам (Ed25519 pubkey). Forward
(`name → addr`) и reverse (`addr → name`) lookup, передача ownership,
освобождение имени.
**Реализация: native Go** (`blockchain/native_username.go`). Работает
без WASM VM — нулевая латентность, не может повесить AddBlock. Старая
WASM-версия заменена; клиенты получают канонический ID через
`/api/well-known-contracts`.
## Ключевые свойства
| | |
|---|---|
| **Contract ID** | `native:username_registry` |
| **Version** | `2.1.0-native` |
| **Регистрация** | Flat fee 10 000 µT (0.01 T), **burn** — никому не идёт |
| **Ограничения имени** | 432 символа, `a-z 0-9 _ -`, первый символ — буква |
| **Зарезервированные** | `system`, `admin`, `root`, `dchain`, `null`, `none` |
| **Один адрес — одно имя** | Чтобы сменить, нужно `release` + `register` |
Комиссия 10 000 µT выбрана как баланс: достаточно дёшево для реальных
пользователей, достаточно дорого чтобы один ID-squatter не забил тысячу
имён из скучающего бота.
## Оплата
Плата передаётся в `tx.Amount` (видна в истории транзакций), контракт
проверяет её точное значение и вычитает из баланса отправителя. Не
направляется никуда — токены сгорают.
Дополнительно платится `tx.Fee = 1 000 µT` за саму транзакцию — это
network fee валидатору, стандартный `MinFee` для любой tx.
Итого: `register(name)` стоит **11 000 µT ≈ 0.011 T**.
## Методы
### `register(name)` — payable 10000
Зарегистрировать имя для `tx.From`.
**Проверки** (в порядке):
1. `name` валиден (длина, символы, не reserved)
2. `tx.Amount == 10 000` (ошибка `register requires tx.amount = 10000 µT`)
3. Имя не занято
4. `tx.From` не владеет другим именем
5. Баланс отправителя достаточен для `amount + fee + gas`
**Успех:**
- Списывает 10 000 µT с баланса (burn)
- `cstate[name:<name>] = tx.From`
- `cstate[addr:<tx.From>] = name`
- Лог `registered: <name> → <pubkey>`
**CLI-пример:**
```bash
client call-contract \
--key my.json \
--contract native:username_registry \
--method register \
--args '["alice"]' \
--amount 10000 \
--node http://localhost:8081
```
**Клиент-приложение** делает это автоматически через Settings →
«Купить никнейм».
### `resolve(name)` — free
Прочитать владельца имени.
Логирует `owner: <pubkey>` или `not found: <name>`. Клиент в HTTP-API
обычно использует прямое чтение state:
```
GET /api/contracts/native:username_registry/state/name:alice
→ { value_hex: "<hex of owner pubkey ASCII>" }
```
### `lookup(address)` — free
Обратный lookup. Логирует `name: <name>` или `no name: <address>`.
Клиент использует `GET .../state/addr:<pubkey>`.
### `transfer(name, new_owner)` — free
Передать `name` другому адресу. Только текущий владелец может вызвать.
Новый владелец не должен уже иметь имя.
### `release(name)` — free
Удалить привязку. Только текущий владелец. Освобождает `name` и
`addr:<caller>` для будущих регистраций.
## State layout
Все ключи записываются в общий namespace `cstate:native:username_registry:`:
| Key | Value |
|-----|-------|
| `name:<name>` | Hex pubkey владельца (64 символа) |
| `addr:<pubkey>` | ASCII-строка с именем |
Значения хранятся как байты; HTTP endpoint
`/api/contracts/:id/state/:key` возвращает их в `value_hex`, клиент
делает `hex → UTF-8` перед показом.
## Клиентская интеграция
- `useWellKnownContracts` хук авто-синхронизирует `settings.contractId =
native:username_registry`
- `resolveUsername(contractId, name)` и `reverseResolve(contractId, addr)`
в `client-app/lib/api.ts` делают HTTP-запрос + hex-decode
- Settings экран покупает никнейм через `buildCallContractTx({amount:
10_000, ...})` + автоматический `reverseResolve` polling после submit
для показа `@name` в профиле за ~1 блок
## Отличия от предыдущей WASM-версии
| | WASM v1 | Native v2 |
|---|---------|-----------|
| **Fee** | 10^(7-len), tiered | Flat 10 000 µT |
| **Fee destination** | Contract treasury | Burn |
| **Min length** | 1 | **4** |
| **Payment point** | Debited inside contract, invisible in tx | `tx.Amount`, visible in history |
| **Latency** | ~10 ms (wazero startup) | ~50 µs (direct Go call) |
| **VM hang risk** | Да (требует timeout) | Нет |
Зарегистрированные в старой WASM-версии имена не мигрируются
автоматически — операторам нужно пере-зарегистрировать после reset
chain (см. `CHANGELOG.md` «Compatibility notes»).