Files
dchain/docs/development/host-functions.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

275 lines
8.0 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.

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