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

268 lines
7.4 KiB
Markdown
Raw 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.

# 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
```