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:
182
scripts/deploy_contracts.sh
Normal file
182
scripts/deploy_contracts.sh
Normal file
@@ -0,0 +1,182 @@
|
||||
#!/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
|
||||
Reference in New Issue
Block a user