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:
vsecoder
2026-04-17 14:16:44 +03:00
commit 7e7393e4f8
196 changed files with 55947 additions and 0 deletions

267
docs/contracts/escrow.md Normal file
View File

@@ -0,0 +1,267 @@
# escrow
Двусторонний trustless escrow. Buyer блокирует средства в contract treasury. Seller выполняет условие. Buyer подтверждает или открывает спор. При споре admin-арбитр решает исход.
## Жизненный цикл
```
buyer seller admin
│ │ │
│─ create ─────▶│ │ treasury ← amount (locked)
│ (seller, │ │ status: active
│ amount) │ │
│ │ │
│ [seller delivered] │
│ │ │
│─ release ────▶│ │ treasury → seller
│ │ │ status: released
OR:
│─ dispute ────▶│ │ status: disputed
│ │─ dispute ────▶│ (either party can)
│ │ │
│ │ │─ resolve(winner=buyer) ──▶
│ │ │ treasury → buyer
│ │ │ status: refunded
│ │ │
│ │ │─ resolve(winner=seller) ──▶
│ │ │ treasury → seller
│ │ │ status: released
OR:
│ │─ refund ─────▶│ treasury → buyer (voluntary)
│ │ │ status: refunded
```
**Статусы:** `active``released` / `refunded` / `disputed`
## Методы
### `init`
Установить caller как admin (арбитр споров).
**Аргументы:** нет
Вызывается один раз после деплоя (deploy-скрипт делает автоматически).
```bash
client call-contract --method init \
--contract $ESC_ID --key /keys/node1.json \
--gas 5000 --node http://node1:8080
```
---
### `create`
Buyer создаёт escrow и блокирует средства.
**Аргументы:**
| # | Имя | Тип | Описание |
|---|-----|-----|---------|
| 0 | `id` | string | Уникальный ID эскроу (задаёт пользователь) |
| 1 | `seller` | string | Pubkey продавца (hex) |
| 2 | `amount` | uint64 | Сумма в µT |
**Поведение:**
- Переводит `amount` с caller (buyer) → treasury
- Сохраняет buyer, seller, amount, status=active
- Лог: `created: <id>`
**Ограничения:**
- ID должен быть уникальным — если `cstate[e:<id>:b]` уже есть, tx отклоняется
```bash
client call-contract --method create \
--arg "deal-001" \
--arg <SELLER_PUBKEY> \
--arg64 10000000 \
--contract $ESC_ID --key /tmp/buyer.json \
--gas 30000 --node http://node1:8080
```
---
### `release`
Buyer подтверждает получение и освобождает средства seller'у.
**Аргументы:**
| # | Имя | Тип |
|---|-----|-----|
| 0 | `id` | string |
**Права:** только buyer.
**Статус:** должен быть `active`.
**Поведение:**
- Переводит `amount` с treasury → seller
- Статус → released
- Лог: `released: <id>`
```bash
client call-contract --method release --arg "deal-001" \
--contract $ESC_ID --key /tmp/buyer.json \
--gas 20000 --node http://node1:8080
```
---
### `refund`
Seller добровольно возвращает деньги buyer'у.
**Аргументы:**
| # | Имя | Тип |
|---|-----|-----|
| 0 | `id` | string |
**Права:** только seller.
**Статус:** должен быть `active`.
**Поведение:**
- Переводит `amount` с treasury → buyer
- Статус → refunded
- Лог: `refunded: <id>`
```bash
client call-contract --method refund --arg "deal-001" \
--contract $ESC_ID --key /tmp/seller.json \
--gas 20000 --node http://node1:8080
```
---
### `dispute`
Открыть спор. Может вызвать buyer или seller.
**Аргументы:**
| # | Имя | Тип |
|---|-----|-----|
| 0 | `id` | string |
**Статус:** должен быть `active`.
**Поведение:**
- Статус → disputed
- Лог: `disputed: <id>`
- Средства остаются заблокированы в treasury
```bash
client call-contract --method dispute --arg "deal-001" \
--contract $ESC_ID --key /tmp/buyer.json \
--gas 10000 --node http://node1:8080
```
---
### `resolve`
Admin разрешает спор.
**Аргументы:**
| # | Имя | Тип | Значения |
|---|-----|-----|---------|
| 0 | `id` | string | ID эскроу |
| 1 | `winner` | string | `buyer` или `seller` |
**Права:** только admin.
**Статус:** должен быть `disputed`.
**Поведение:**
- `winner=buyer` → treasury → buyer, статус → refunded
- `winner=seller` → treasury → seller, статус → released
- Лог: `resolved: <id>`
```bash
# Admin решает в пользу buyer
client call-contract --method resolve \
--arg "deal-001" --arg buyer \
--contract $ESC_ID --key /keys/node1.json \
--gas 20000 --node http://node1:8080
# Admin решает в пользу seller
client call-contract --method resolve \
--arg "deal-001" --arg seller \
--contract $ESC_ID --key /keys/node1.json \
--gas 20000 --node http://node1:8080
```
---
### `info`
Запросить состояние эскроу.
**Аргументы:**
| # | Имя | Тип |
|---|-----|-----|
| 0 | `id` | string |
**Логи:**
```
buyer: <pubkey>
seller: <pubkey>
amount: <µT>
status: active|released|refunded|disputed
```
```bash
client call-contract --method info --arg "deal-001" \
--contract $ESC_ID --key /keys/node1.json \
--gas 5000 --node http://node1:8080
```
---
## State Layout
```
cstate:<contractID>:admin → admin pubkey
cstate:<contractID>:e:<id>:b → buyer pubkey
cstate:<contractID>:e:<id>:s → seller pubkey
cstate:<contractID>:e:<id>:a → amount (uint64 big-endian)
cstate:<contractID>:e:<id>:x → status byte ('a'=active, 'd'=disputed, 'r'=released, 'f'=refunded)
```
## Полный сценарий с dispute
```bash
# Параметры
BUYER_KEY=/tmp/buyer.json
SELLER_KEY=/tmp/seller.json
ADMIN_KEY=/keys/node1.json
ID="escrow-001"
# 1. Buyer создаёт эскроу на 5 T
docker exec node1 client call-contract \
--key $BUYER_KEY --contract $ESC_ID \
--method create \
--arg $ID --arg $SELLER_PUB --arg64 5000000 \
--gas 30000 --node http://node1:8080
# 2. Проверить статус
docker exec node1 client call-contract \
--key $BUYER_KEY --contract $ESC_ID \
--method info --arg $ID \
--gas 5000 --node http://node1:8080
# status: active
# 3. Buyer не доволен — открывает спор
docker exec node1 client call-contract \
--key $BUYER_KEY --contract $ESC_ID \
--method dispute --arg $ID \
--gas 10000 --node http://node1:8080
# 4. Admin рассматривает дело и решает в пользу seller
docker exec node1 client call-contract \
--key $ADMIN_KEY --contract $ESC_ID \
--method resolve --arg $ID --arg seller \
--gas 20000 --node http://node1:8080
# Лог: resolved: escrow-001
# Seller получает 5 T
```