Files
dchain/scripts/deploy_contracts.sh
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

183 lines
7.2 KiB
Bash
Raw Permalink 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.

#!/bin/sh
# deploy_contracts.sh — деплой всех 4 production-контрактов из genesis-кошелька.
#
# Запуск:
# docker compose --profile deploy run --rm deploy
#
# После деплоя contract_id'ы выводятся в stdout и сохраняются в /tmp/contracts.env.
# Контракты видны в Explorer: http://localhost:8081/contracts
set -e
# ── Конфигурация нод (через backbone IP, без DNS) ─────────────────────────────
NODE1_URL="${NODE1_URL:-http://172.30.0.11:8080}"
NODE2_URL="${NODE2_URL:-http://172.30.0.12:8080}"
NODE3_URL="${NODE3_URL:-http://172.30.0.13:8080}"
# Основная нода для деплоя (genesis-кошелёк на node1)
NODE="$NODE1_URL"
GENESIS_KEY="/keys/node1.json"
BOLD='\033[1m'
CYAN='\033[1;36m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
RESET='\033[0m'
step() { printf "\n${CYAN}▶ %s${RESET}\n" "$*"; }
ok() { printf " ${GREEN}${RESET} %s\n" "$*"; }
fail() { printf " ${RED}${RESET} %s\n" "$*"; exit 1; }
info() { printf " %s\n" "$*"; }
# ── Ожидание готовности ноды ──────────────────────────────────────────────────
wait_node() {
local name="$1" url="$2"
step "Ожидание готовности $name ($url)..."
i=0
while [ $i -lt 90 ]; do
if wget -qO /dev/null "$url/api/netstats" 2>/dev/null; then
ok "$name доступен"; break
fi
printf "."; sleep 1; i=$((i+1))
done
[ $i -lt 90 ] || fail "$name недоступен после 90 секунд"
}
wait_node "node1" "$NODE1_URL"
wait_node "node2" "$NODE2_URL"
wait_node "node3" "$NODE3_URL"
printf " Ждём genesis block на node1"
i=0
while [ $i -lt 60 ]; do
if wget -qO- "$NODE/api/netstats" 2>/dev/null | grep -q '"total_blocks": *[1-9]'; then
printf " — готово.\n"; break
fi
printf "."; sleep 1; i=$((i+1))
done
[ $i -lt 60 ] || fail "Genesis block не появился"
# ── Хелпер: деплой одного контракта ──────────────────────────────────────────
deploy_contract() {
local name="$1" wasm="$2" abi="$3"
step "Деплой $name"
OUT=$(client deploy-contract \
--key "$GENESIS_KEY" \
--wasm "$wasm" \
--abi "$abi" \
--node "$NODE" 2>&1)
printf '%s\n' "$OUT"
CID=$(printf '%s' "$OUT" | grep 'contract_id:' | awk '{print $NF}')
[ -n "$CID" ] || fail "Не удалось получить contract_id для $name"
# Ждём подтверждения on-chain
printf " Ждём подтверждения"
i=0
while [ $i -lt 40 ]; do
if wget -qO- "$NODE/api/contracts/$CID" 2>/dev/null | grep -q '"contract_id"'; then
printf " — задеплоен.\n"; break
fi
printf "."; sleep 1; i=$((i+1))
done
[ $i -lt 40 ] || fail "Timeout ожидания контракта $name"
ok "$name contract_id: $CID"
echo "$CID"
}
# ── Инициализация контракта (вызов init) ──────────────────────────────────────
init_contract() {
local name="$1" cid="$2"
step "Инициализация $name (вызов init)"
client call-contract \
--key "$GENESIS_KEY" \
--contract "$cid" \
--method init \
--gas 50000 \
--node "$NODE" 2>&1 | grep -v '^$' || true
sleep 2
ok "$name инициализирован"
}
# ── Деплой всех контрактов ────────────────────────────────────────────────────
printf "\n${YELLOW}══════════════════════════════════════════════════${RESET}\n"
printf "${BOLD} DChain — деплой production-контрактов${RESET}\n"
printf "${YELLOW}══════════════════════════════════════════════════${RESET}\n"
UR_ID=$(deploy_contract "username_registry" \
"/keys/username_registry.wasm" \
"/keys/username_registry_abi.json")
GOV_ID=$(deploy_contract "governance" \
"/keys/governance.wasm" \
"/keys/governance_abi.json")
AUC_ID=$(deploy_contract "auction" \
"/keys/auction.wasm" \
"/keys/auction_abi.json")
ESC_ID=$(deploy_contract "escrow" \
"/keys/escrow.wasm" \
"/keys/escrow_abi.json")
# Инициализируем контракты с admin-ролью
init_contract "governance" "$GOV_ID"
init_contract "escrow" "$ESC_ID"
# ── Линковка governance со всеми нодами (runtime, без перезапуска) ────────────
link_governance() {
local name="$1" url="$2"
step "Линковка governance с $name ($url)"
RESP=$(wget -qO- --post-data="{\"governance\":\"$GOV_ID\"}" \
--header="Content-Type: application/json" \
"$url/api/governance/link" 2>/dev/null || true)
if printf '%s' "$RESP" | grep -q '"ok"'; then
ok "governance привязан — gas_price управляется on-chain"
else
info "нода недоступна или уже настроена: $RESP"
fi
}
link_governance "node1" "$NODE1_URL"
link_governance "node2" "$NODE2_URL"
link_governance "node3" "$NODE3_URL"
# ── Итоговый вывод ────────────────────────────────────────────────────────────
printf "\n${YELLOW}══════════════════════════════════════════════════${RESET}\n"
printf "${BOLD} Все контракты задеплоены!${RESET}\n"
printf "${YELLOW}══════════════════════════════════════════════════${RESET}\n\n"
ok "username_registry : $UR_ID"
ok "governance : $GOV_ID"
ok "auction : $AUC_ID"
ok "escrow : $ESC_ID"
printf "\n${BOLD}Explorer:${RESET}\n"
info "node1 → http://localhost:8081/contracts"
info "node2 → http://localhost:8082/contracts"
info "node3 → http://localhost:8083/contracts"
printf "\n"
info "http://localhost:8081/contract?id=$UR_ID (username_registry)"
info "http://localhost:8081/contract?id=$GOV_ID (governance)"
info "http://localhost:8081/contract?id=$AUC_ID (auction)"
info "http://localhost:8081/contract?id=$ESC_ID (escrow)"
# Сохраняем ID для последующего использования
cat > /tmp/contracts.env << EOF
USERNAME_REGISTRY=$UR_ID
GOVERNANCE=$GOV_ID
AUCTION=$AUC_ID
ESCROW=$ESC_ID
EOF
printf "\n"
ok "ID сохранены в /tmp/contracts.env"
echo