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
This commit is contained in:
133
docs/contracts/username_registry.md
Normal file
133
docs/contracts/username_registry.md
Normal file
@@ -0,0 +1,133 @@
|
||||
# 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** — никому не идёт |
|
||||
| **Ограничения имени** | 4–32 символа, `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»).
|
||||
Reference in New Issue
Block a user