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,274 @@
# Host Functions
Полный справочник 14 host-функций, которые DChain экспортирует в WASM-контракты через модуль `env`.
Все функции регистрируются в `vm/host.go`. Контракт импортирует их через `//go:wasmimport env <name>` (TinyGo) или напрямую в секции `imports` WASM-модуля.
---
## Аргументы
### `get_args`
```
get_args(dstPtr i32, dstLen i32) → written i32
```
Читает весь JSON-массив аргументов транзакции в буфер `[dstPtr, dstPtr+dstLen)`.
Возвращает количество записанных байт (0 если аргументов нет).
---
### `get_arg_str`
```
get_arg_str(idx i32, dstPtr i32, dstLen i32) → written i32
```
Читает аргумент с индексом `idx` как строку (без кавычек JSON).
`dstLen` — максимальная длина буфера.
Возвращает 0 если аргумент не существует или тип не строка.
**SDK:** `dc.ArgStr(idx, maxLen)`
---
### `get_arg_u64`
```
get_arg_u64(idx i32) → val i64
```
Читает аргумент с индексом `idx` как беззнаковое 64-битное число.
Возвращает 0 если индекс вне диапазона или тип не число.
**SDK:** `dc.ArgU64(idx)`
---
## State
### `get_state_len`
```
get_state_len(keyPtr i32, keyLen i32) → valLen i32
```
Возвращает размер значения по ключу (0 если ключ не найден).
Используется перед `get_state` для выделения буфера нужного размера.
---
### `get_state`
```
get_state(keyPtr i32, keyLen i32, dstPtr i32, dstLen i32) → written i32
```
Читает `min(len(value), dstLen)` байт по ключу в буфер.
Возвращает фактически записанное количество байт.
**SDK:** `dc.GetState(key)` (выделяет буфер автоматически через `get_state_len`)
---
### `set_state`
```
set_state(keyPtr i32, keyLen i32, valPtr i32, valLen i32)
```
Записывает значение по ключу. Если `valLen == 0` — удаляет ключ.
**SDK:** `dc.SetState(key, value)`, `dc.SetStateStr(key, s)`, `dc.PutU64(key, v)`
---
### `put_u64`
```
put_u64(keyPtr i32, keyLen i32, val i64)
```
Записывает `val` как 8 байт big-endian. Эквивалентно `set_state` с 8-байтным big-endian значением, но компактнее в вызове.
**SDK:** `dc.PutU64(key, v)`
---
### `get_u64`
```
get_u64(keyPtr i32, keyLen i32) → val i64
```
Читает 8 байт big-endian по ключу. Возвращает 0 если ключ не найден.
**SDK:** `dc.GetU64(key)`
---
## Идентификация
### `get_caller`
```
get_caller(bufPtr i32, bufLen i32) → written i32
```
Записывает hex-pubkey вызывающего аккаунта (64 символа ASCII).
Если `bufLen < 64`, записывает частично.
**SDK:** `dc.Caller()`
---
### `get_block_height`
```
get_block_height() → height i64
```
Возвращает высоту текущего блока (в котором исполняется транзакция).
**SDK:** `dc.BlockHeight()`
---
### `get_contract_treasury`
```
get_contract_treasury(bufPtr i32, bufLen i32) → written i32
```
Записывает hex-pubkey treasury контракта (64 символа).
Treasury — специальный счёт, привязанный к контракту. Контракт может переводить с treasury как `from` без ограничений.
**SDK:** `dc.Treasury()`
---
## Токены
### `get_balance`
```
get_balance(pubPtr i32, pubLen i32) → balance i64
```
Возвращает баланс адреса в µT (микро-токены).
**SDK:** `dc.Balance(pubKeyHex)`
---
### `transfer`
```
transfer(fromPtr i32, fromLen i32, toPtr i32, toLen i32, amount i64) → errCode i32
```
Переводит `amount` µT с `from` на `to`.
Возвращает 0 при успехе, 1 при ошибке (недостаточно средств, неверный адрес).
**Ограничения:**
- `from` должен быть либо `dc.Caller()`, либо `dc.Treasury()`.
- Контракт не может тратить чужие деньги (только caller'а или свой treasury).
**SDK:** `dc.Transfer(from, to, amount) bool`
---
## Межконтрактные вызовы
### `call_contract`
```
call_contract(cidPtr i32, cidLen i32, mthPtr i32, mthLen i32, argPtr i32, argLen i32) → errCode i32
```
Вызывает метод другого контракта.
| Параметр | Тип | Описание |
|---------|-----|---------|
| `cidPtr/cidLen` | i32 | hex-ID целевого контракта (16 символов) |
| `mthPtr/mthLen` | i32 | имя метода |
| `argPtr/argLen` | i32 | JSON-массив аргументов |
**Возврат:** 0 = успех, 1 = ошибка (превышена глубина, контракт не найден, и т.д.)
**Gas:** подвызов получает `gc.Remaining()` от родительского счётчика. Потраченный gas вычитается из родителя.
**State:** все вызовы в цепочке разделяют одну `badger.Txn`. Если подвызов не падает, его изменения видны родителю.
**Подробнее:** [Межконтрактные вызовы](inter-contract.md)
**SDK:** `dc.CallContract(contractID, method, argsJSON) bool`
---
## Логирование
### `log`
```
log(msgPtr i32, msgLen i32)
```
Записывает строку в лог контракта. Логи привязаны к транзакции и видны в Explorer → вкладка Logs.
`fmt.Println` и `log.Printf` через WASI stdout **не** попадают в блокчейн-логи. Используйте только `log`.
**SDK:** `dc.Log(msg)`
---
## Gas
### `gas_tick`
```
gas_tick()
```
Вызывается автоматически при каждой итерации цикла в бинарных WASM-контрактах (инструментация вручную). Списывает 1 unit gas.
Для TinyGo-контрактов TinyGo генерирует собственную инструментацию.
---
## Таблица функций
| # | Имя | Сигнатура | SDK |
|---|-----|----------|-----|
| 1 | `get_args` | `(i32,i32)→i32` | — |
| 2 | `get_arg_str` | `(i32,i32,i32)→i32` | `ArgStr` |
| 3 | `get_arg_u64` | `(i32)→i64` | `ArgU64` |
| 4 | `get_state_len` | `(i32,i32)→i32` | внутри `GetState` |
| 5 | `get_state` | `(i32,i32,i32,i32)→i32` | `GetState` |
| 6 | `set_state` | `(i32,i32,i32,i32)` | `SetState` |
| 7 | `put_u64` | `(i32,i32,i64)` | `PutU64` |
| 8 | `get_u64` | `(i32,i32)→i64` | `GetU64` |
| 9 | `get_caller` | `(i32,i32)→i32` | `Caller` |
| 10 | `get_block_height` | `()→i64` | `BlockHeight` |
| 11 | `get_contract_treasury` | `(i32,i32)→i32` | `Treasury` |
| 12 | `get_balance` | `(i32,i32)→i64` | `Balance` |
| 13 | `transfer` | `(i32,i32,i32,i32,i64)→i32` | `Transfer` |
| 14 | `call_contract` | `(i32,i32,i32,i32,i32,i32)→i32` | `CallContract` |
| 15 | `log` | `(i32,i32)` | `Log` |
| 16 | `gas_tick` | `()` | — |
---
## Паттерн прямого импорта (без SDK)
Если вы пишете бинарный WASM вручную (без TinyGo), функции импортируются в секции `imports`:
```
(import "env" "get_state_len" (func (param i32 i32) (result i32)))
(import "env" "get_state" (func (param i32 i32 i32 i32) (result i32)))
(import "env" "set_state" (func (param i32 i32 i32 i32)))
...
```
Подробнее: [Бинарный WASM](binary-wasm.md)