188 lines
4.7 KiB
Bash
188 lines
4.7 KiB
Bash
#!/bin/bash
|
||
# =============================================================================
|
||
# 热钱包 MPC 初始化脚本
|
||
# =============================================================================
|
||
#
|
||
# 用途: 创建系统热钱包的 MPC 密钥,用于提现转账
|
||
#
|
||
# 前提条件:
|
||
# 1. mpc-service 正在运行
|
||
# 2. mpc-system 正在运行且所有 party 已启动
|
||
#
|
||
# 使用方法:
|
||
# ./init-hot-wallet.sh [options]
|
||
#
|
||
# 选项:
|
||
# -u, --username 热钱包用户名 (默认: system-hot-wallet)
|
||
# -n, --threshold-n 总 party 数量 (默认: 3)
|
||
# -t, --threshold-t 签名门限值 (默认: 2)
|
||
# -h, --host mpc-service 地址 (默认: http://localhost:3013)
|
||
# --help 显示帮助
|
||
#
|
||
# =============================================================================
|
||
|
||
set -e
|
||
|
||
# 默认配置
|
||
USERNAME="system-hot-wallet"
|
||
THRESHOLD_N=3
|
||
THRESHOLD_T=2
|
||
MPC_HOST="http://localhost:3013"
|
||
|
||
# 解析参数
|
||
while [[ $# -gt 0 ]]; do
|
||
case $1 in
|
||
-u|--username)
|
||
USERNAME="$2"
|
||
shift 2
|
||
;;
|
||
-n|--threshold-n)
|
||
THRESHOLD_N="$2"
|
||
shift 2
|
||
;;
|
||
-t|--threshold-t)
|
||
THRESHOLD_T="$2"
|
||
shift 2
|
||
;;
|
||
-h|--host)
|
||
MPC_HOST="$2"
|
||
shift 2
|
||
;;
|
||
--help)
|
||
head -30 "$0" | tail -25
|
||
exit 0
|
||
;;
|
||
*)
|
||
echo "未知参数: $1"
|
||
exit 1
|
||
;;
|
||
esac
|
||
done
|
||
|
||
echo "=============================================="
|
||
echo "热钱包 MPC 初始化"
|
||
echo "=============================================="
|
||
echo "用户名: $USERNAME"
|
||
echo "门限: $THRESHOLD_T-of-$THRESHOLD_N"
|
||
echo "MPC 服务: $MPC_HOST"
|
||
echo "=============================================="
|
||
echo ""
|
||
|
||
# Step 1: 创建 Keygen 会话
|
||
echo "[1/4] 创建 Keygen 会话..."
|
||
KEYGEN_RESPONSE=$(curl -s -X POST "$MPC_HOST/mpc/keygen" \
|
||
-H "Content-Type: application/json" \
|
||
-d "{
|
||
\"username\": \"$USERNAME\",
|
||
\"thresholdN\": $THRESHOLD_N,
|
||
\"thresholdT\": $THRESHOLD_T,
|
||
\"requireDelegate\": true
|
||
}")
|
||
|
||
SESSION_ID=$(echo "$KEYGEN_RESPONSE" | jq -r '.sessionId')
|
||
STATUS=$(echo "$KEYGEN_RESPONSE" | jq -r '.status')
|
||
|
||
if [ "$SESSION_ID" == "null" ] || [ -z "$SESSION_ID" ]; then
|
||
echo "错误: 创建 Keygen 会话失败"
|
||
echo "响应: $KEYGEN_RESPONSE"
|
||
exit 1
|
||
fi
|
||
|
||
echo "会话 ID: $SESSION_ID"
|
||
echo "状态: $STATUS"
|
||
echo ""
|
||
|
||
# Step 2: 轮询等待 Keygen 完成
|
||
echo "[2/4] 等待 Keygen 完成..."
|
||
MAX_ATTEMPTS=180 # 最多等待 6 分钟
|
||
ATTEMPT=0
|
||
PUBLIC_KEY=""
|
||
|
||
while [ $ATTEMPT -lt $MAX_ATTEMPTS ]; do
|
||
STATUS_RESPONSE=$(curl -s -X GET "$MPC_HOST/mpc/keygen/$SESSION_ID/status")
|
||
STATUS=$(echo "$STATUS_RESPONSE" | jq -r '.status')
|
||
PUBLIC_KEY=$(echo "$STATUS_RESPONSE" | jq -r '.publicKey // empty')
|
||
|
||
echo " 轮询 #$((ATTEMPT + 1)): 状态=$STATUS"
|
||
|
||
if [ "$STATUS" == "completed" ]; then
|
||
echo ""
|
||
echo "Keygen 完成!"
|
||
break
|
||
fi
|
||
|
||
if [ "$STATUS" == "failed" ] || [ "$STATUS" == "expired" ]; then
|
||
echo ""
|
||
echo "错误: Keygen 失败,状态=$STATUS"
|
||
exit 1
|
||
fi
|
||
|
||
ATTEMPT=$((ATTEMPT + 1))
|
||
sleep 2
|
||
done
|
||
|
||
if [ "$STATUS" != "completed" ]; then
|
||
echo "错误: Keygen 超时"
|
||
exit 1
|
||
fi
|
||
|
||
# Step 3: 显示公钥
|
||
echo ""
|
||
echo "[3/4] 获取公钥..."
|
||
if [ -z "$PUBLIC_KEY" ]; then
|
||
# 再次获取状态以确保拿到公钥
|
||
STATUS_RESPONSE=$(curl -s -X GET "$MPC_HOST/mpc/keygen/$SESSION_ID/status")
|
||
PUBLIC_KEY=$(echo "$STATUS_RESPONSE" | jq -r '.publicKey')
|
||
fi
|
||
|
||
if [ -z "$PUBLIC_KEY" ] || [ "$PUBLIC_KEY" == "null" ]; then
|
||
echo "错误: 无法获取公钥"
|
||
exit 1
|
||
fi
|
||
|
||
echo "公钥: $PUBLIC_KEY"
|
||
|
||
# Step 4: 从公钥派生 EVM 地址
|
||
echo ""
|
||
echo "[4/4] 派生 EVM 地址..."
|
||
|
||
# 使用 node 计算地址(如果安装了 ethers)
|
||
if command -v node &> /dev/null; then
|
||
ADDRESS=$(node -e "
|
||
const { computeAddress } = require('ethers');
|
||
try {
|
||
const address = computeAddress('0x$PUBLIC_KEY');
|
||
console.log(address);
|
||
} catch (e) {
|
||
console.error('Error:', e.message);
|
||
process.exit(1);
|
||
}
|
||
" 2>/dev/null || echo "")
|
||
|
||
if [ -n "$ADDRESS" ] && [ "$ADDRESS" != "Error:"* ]; then
|
||
echo "EVM 地址: $ADDRESS"
|
||
else
|
||
echo "提示: 无法自动计算地址,请手动计算"
|
||
echo "公钥 (hex): $PUBLIC_KEY"
|
||
fi
|
||
else
|
||
echo "提示: 未安装 Node.js,请手动从公钥计算 EVM 地址"
|
||
echo "公钥 (hex): $PUBLIC_KEY"
|
||
fi
|
||
|
||
echo ""
|
||
echo "=============================================="
|
||
echo "初始化完成!"
|
||
echo "=============================================="
|
||
echo ""
|
||
echo "请将以下配置添加到 blockchain-service 的环境变量:"
|
||
echo ""
|
||
echo " HOT_WALLET_USERNAME=$USERNAME"
|
||
if [ -n "$ADDRESS" ] && [ "$ADDRESS" != "Error:"* ]; then
|
||
echo " HOT_WALLET_ADDRESS=$ADDRESS"
|
||
else
|
||
echo " HOT_WALLET_ADDRESS=<从公钥计算的地址>"
|
||
fi
|
||
echo ""
|
||
echo "=============================================="
|