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

View File

@@ -0,0 +1,203 @@
# governance
On-chain governance контракт для управления параметрами сети. Deployer становится admin. Любой может предложить изменение параметра; admin принимает или отклоняет.
## Концепция
```
Участник Admin
│ │
│── propose ──▶ │ state[prop:<key>] = value
│ │
│ │── approve ──▶ state[param:<key>] = value (live)
│ │ удаляет prop:<key>
│ │
│ │── reject ──▶ удаляет prop:<key>
```
После approve параметр становится **live** и читается нодой при следующем вызове контракта.
## Методы
### `init`
Инициализировать контракт, установить caller как admin.
**Аргументы:** нет
**Вызывается:** один раз после деплоя (deploy-скрипт делает это автоматически).
**Поведение:**
- Устанавливает `state[admin] = caller_pubkey`
- Идемпотентен: повторный вызов не меняет admin если уже установлен
```bash
client call-contract --method init --contract $GOV_ID \
--key /keys/node1.json --gas 5000 --node http://node1:8080
```
---
### `propose`
Предложить новое значение параметра. Доступно всем.
**Аргументы:**
| # | Имя | Тип | Ограничение |
|---|-----|-----|------------|
| 0 | `key` | string | max 64 байта |
| 1 | `value` | string | max 256 байт |
**Поведение:**
- Сохраняет `state[prop:<key>] = value`
- Лог: `proposed: <key>=<value>`
- Если pending-предложение уже есть → перезаписывает
```bash
# Предложить новую цену газа 5 µT/gas
client call-contract --method propose \
--arg gas_price --arg 5 \
--contract $GOV_ID --key /keys/node1.json \
--gas 10000 --node http://node1:8080
```
---
### `approve`
Admin принимает pending-предложение. Параметр становится live.
**Аргументы:**
| # | Имя | Тип |
|---|-----|-----|
| 0 | `key` | string |
**Права:** только admin.
**Поведение:**
- Копирует `state[prop:<key>]``state[param:<key>]`
- Удаляет `state[prop:<key>]`
- Лог: `approved: <key>`
- Если нет pending → лог `no pending: <key>`
```bash
client call-contract --method approve --arg gas_price \
--contract $GOV_ID --key /keys/node1.json \
--gas 10000 --node http://node1:8080
```
---
### `reject`
Admin отклоняет pending-предложение.
**Аргументы:**
| # | Имя | Тип |
|---|-----|-----|
| 0 | `key` | string |
**Права:** только admin.
```bash
client call-contract --method reject --arg gas_price \
--contract $GOV_ID --key /keys/node1.json \
--gas 5000 --node http://node1:8080
```
---
### `get`
Прочитать текущее live-значение параметра.
**Аргументы:**
| # | Имя | Тип |
|---|-----|-----|
| 0 | `key` | string |
**Лог:**
- `value: <value>` — параметр установлен
- `not set: <key>` — параметр не установлен
```bash
client call-contract --method get --arg gas_price \
--contract $GOV_ID --key /keys/node1.json \
--gas 3000 --node http://node1:8080
```
Через REST (без транзакции):
```bash
curl http://localhost:8081/api/contracts/$GOV_ID/state/param:gas_price
```
---
### `get_pending`
Прочитать pending-предложение.
**Аргументы:**
| # | Имя | Тип |
|---|-----|-----|
| 0 | `key` | string |
**Лог:**
- `pending: <value>`
- `no pending: <key>`
---
### `set_admin`
Передать роль admin другому адресу.
**Аргументы:**
| # | Имя | Тип |
|---|-----|-----|
| 0 | `new_admin` | string (hex pubkey) |
**Права:** только текущий admin.
```bash
client call-contract --method set_admin --arg <NEW_ADMIN_PUBKEY> \
--contract $GOV_ID --key /keys/node1.json \
--gas 10000 --node http://node1:8080
```
---
## Управляемые параметры
Governance хранит произвольные string-параметры. Нода читает следующие:
| Ключ | Тип | Описание | По умолчанию |
|------|-----|---------|-------------|
| `gas_price` | uint64 (строка) | µT за 1 gas unit | 1 µT |
> Нода читает `gas_price` при каждом `CALL_CONTRACT` через `chain.GetEffectiveGasPrice()`.
> Изменение вступает в силу немедленно после `approve` — без перезапуска.
Можно хранить любые параметры приложения (messenger_entry_fee, relay_fee, etc.) и читать их из других контрактов через межконтрактные вызовы.
## State Layout
```
cstate:<contractID>:admin → admin pubkey (hex string bytes)
cstate:<contractID>:param:<key> → live value
cstate:<contractID>:prop:<key> → pending proposal
```
## Интеграция с нодой
После деплоя governance необходимо его **привязать** к ноде:
```bash
# Автоматически через deploy-скрипт
# Или вручную:
curl -X POST http://localhost:8081/api/governance/link \
-H "Content-Type: application/json" \
-d "{\"governance\": \"$GOV_ID\"}"
```
Подробнее: [Governance интеграция](../node/governance.md)