运营商

什么是 Private Channels 运营商?

运营商是一个受信任的、经过链上授权的实体,负责桥接 Solana 主网与私有通道网络。运营商由实例管理员通过 AddOperator 进行配置,该操作会创建一个链上 Operator PDA;没有此配置,任何参与方都无法调用 ReleaseFunds。实际上,运营商是一个组织或团队,负责运行以下服务:监听存款、在通道侧铸造代币、检测提款,并将资金结算回主网。运行一个实例可为您的用户提供不在 Solana 主网上显示的私密大额转账、超越原生 Solana TPS 的即时零费用吞吐量,以及通过 RBAC 实现的受控访问。

如果您是开发者,需要对接已有的 Private Channels 实例而非自行部署,请从 快速入门开始。

开始之前

前提条件

在主机上固定以下版本以匹配 Docker 镜像:

  • Docker Engine 26+(macOS Apple Silicon:在「设置」->「虚拟机选项」中启用「Docker VMM」)
  • Node.js 24.7.0 和 pnpm 10.15.1
  • Solana CLI 3.1.13(Agave)
  • Rust 1.91.0
  • 用于 Devnet 的 Yellowstone gRPC 端点(可从 Helius、Triton、QuickNode 获取)

有关网络要求和默认端口分配,请参阅仓库中的 docs/TECHNICAL_REQUIREMENTS.md。

安装固定版本的 Solana 工具链并预热 SBF 缓存:

make install-toolchain

服务

运行一个 Private Channels 实例意味着承担五项持续性职责,每项职责由 Docker Compose 栈中的专用容器负责处理:

  1. 索引主网存款 - indexer-solana 通过 Yellowstone gRPC 监听 Solana 主网上的 Deposit 事件;operator-solana 拾取已确认的存款,并在通道网络上铸造等值代币余额
  2. 索引通道提款 - indexer-private-channel 每秒轮询通道,检测 WithdrawFunds 销毁事件,并将待处理的提款记录写入数据库
  3. 在主网释放资金 - operator-private-channel 拾取待处理记录,并携带有效的 SMT 排除证明调用 Escrow Program 上的 ReleaseFunds
  4. 管理 SMT 根 - operator-private-channel 在树 epoch 轮换时自动调用 ResetSmtRoot;链上的 verify_smt_exclusion_proof 检查是防止未授权提款的最后一道防线
  5. 运行网关和认证服务 - 网关是所有客户端流量的唯一公共端点;认证服务(可选)在设置 JWT_SECRET 时强制执行 JWT/RBAC

有关完整的服务清单和端口分配,请参阅 配置参考。

安全说明: 写节点和读节点端口仅绑定到回环地址 (127.0.0.1),但其他几项服务(网关、认证、运营商指标、Grafana、Prometheus、cAdvisor)默认发布到所有网络接口。有关完整的端口表,请参阅 配置参考, 并在任何面向公众的部署之前配置防火墙规则。RBAC 仅覆盖网关自身的 JSON-RPC 方法,不涵盖这些其他服务。

访问控制:开放模式与 RBAC

默认情况下,网关接受所有连接,无需任何令牌。要启用基于 JWT 的 RBAC,请设置 JWT_SECRET 并使用 --profile auth 启动服务栈。完整的配置参考(包括如何配置 operator 角色和注册用户钱包)请参阅 认证与角色。

如果要启用认证,请在启动服务栈之前将以下内容添加到您的环境变量中:

JWT_SECRET=<openssl rand -hex 32> # must match on gateway and auth service
AUTH_PORT=8903

环境配置

.env.devnet 已在仓库中被追踪,并填入了 Devnet 专用的默认值;请直接编辑该文件,而不要从 .env.example 重新生成,否则会覆盖这些默认值。

在执行以下部署步骤时,逐步填入剩余的值;其中部分值仅在部署过程中才能获取。密钥存放在已被 gitignore 的 .env 文件中;非密钥变量存放在 .env.devnet 中。

密钥 - 请立即设置:

POSTGRES_PASSWORD=<openssl rand -hex 32>
POSTGRES_REPLICATION_PASSWORD=<openssl rand -hex 32>

部署过程中获取的变量:

ESCROW_INSTANCE_ID=<instance address - from Step 3>
ADMIN_PRIVATE_KEY=<operator keypair as u8 array or base58 - from Step 4>
DEVNET_RPC_URL=https://api.devnet.solana.com
DEVNET_YELLOWSTONE_ENDPOINT=<your Yellowstone gRPC endpoint>
INDEXER_YELLOWSTONE_TOKEN=<your Yellowstone auth token>

ADMIN_PRIVATE_KEY 是链下服务自身所需的费用支付签名者,与第 3 步中的链上实例管理员无关。本指南将第 4 步生成的运营商 keypair 填入 ADMIN_PRIVATE_KEY,并将可选的 OPERATOR_PRIVATE_KEY 留空,因此运营商签名者将回退使用相同的密钥。请勿将第 3 步中协议级别的实例管理员 keypair 填入上述任何一个变量。

有关完整的环境变量参考,请参阅 配置。

部署

构建镜像

make docker-devnet-build

此命令将所有 Rust 服务编译到一个共享的 Docker 镜像中。首次构建需要 30 分钟到一小时。

配置 Admin UI

Admin UI 是一个基于浏览器的工具,用于创建和配置 Escrow 实例:它是一个开发和管理工具,而非面向用户的产品,也不是必须的运行时组件。其所有操作(CreateInstance、AllowMint、AddOperator)也可通过仓库中的 CLI 脚本执行。

cd admin-ui
pnpm install
echo "PRIVATE_CHANNEL_RPC_URL=http://localhost:8899" > .env
pnpm dev # opens at http://localhost:5173

创建 Escrow 实例

  1. 将您的浏览器钱包切换到 Devnet,并确保您有用于支付费用的 Devnet SOL
  2. 在 Admin UI 中,点击 Create New Instance 并批准交易
  3. 复制 Instance Address 并将其设置为 .env.devnet 中的 ESCROW_INSTANCE_ID

或者,使用 CLI 脚本:

cargo run --bin create_instance -- https://api.devnet.solana.com ./keypairs/admin.json

生成运营商 keypair

solana-keygen new -o operator-keypair.json -s --no-bip39-passphrase
solana-keygen pubkey operator-keypair.json

将 keypair 内容设置为环境变量中的 ADMIN_PRIVATE_KEY。公钥不是环境变量;您将在下方「配置实例」步骤中直接以运营商 pubkey 的形式传入。

完善环境变量

在 .env.devnet 中更新 ESCROW_INSTANCE_ID、DEVNET_RPC_URL、DEVNET_YELLOWSTONE_ENDPOINT 和 INDEXER_YELLOWSTONE_TOKEN。将密钥(POSTGRES_PASSWORD、POSTGRES_REPLICATION_PASSWORD、ADMIN_PRIVATE_KEY)存放在已被 gitignore 的 .env 文件中。

如果您决定启用 RBAC (访问控制:开放模式与 RBAC),请同时在此添加 JWT_SECRET 和 AUTH_PORT。

启动所有服务

不启用认证:

make docker-devnet-up

启用认证:

docker compose -f docker-compose.devnet.yml --env-file versions.env --env-file .env.devnet --env-file .env --profile auth up -d

一旦传入任意 --env-file 标志,Compose 将禁用其自动加载 .env 的功能,因此末尾的 --env-file .env 是必需的。若缺少它,POSTGRES_PASSWORD、ADMIN_PRIVATE_KEY 和 JWT_SECRET(即您存放在 .env 中的值)将解析为空,导致服务栈无法正常启动。

请在配置实例之前先启动服务。Indexer 实时流式处理事件,因此先启动服务栈可确保 AllowMint 和您的首笔存款按顺序被索引,无需回填。

配置实例

服务栈运行后,通过 Admin UI 将代币 Mint 加入白名单并添加您的运营商:

  1. Allow Mint:Admin Functions -> Mint Management -> 输入 Mint 地址 -> Allow Mint
  2. Add Operator:Admin Functions -> Operator Management -> 输入运营商 pubkey -> Add Operator

或通过 CLI:

cargo run --bin add_operator -- \
https://api.devnet.solana.com \
./keypairs/admin.json \
<INSTANCE_ID> \
<OPERATOR_PUBKEY>

本指南面向 Solana Devnet。若使用主网,请注意:

  • 程序 ID 通过 declare_id!() 编译嵌入:请确认您使用的是仓库中正确的主网 ID
  • Yellowstone gRPC 端点需要主网套餐;Devnet 端点不会流式传输主网事件
  • 运营商钱包每次调用 ReleaseFunds 都需支付 SOL 费用,请根据预期的提款量规划 SOL 余额
  • 在任何面向公众的部署之前,请更改所有默认凭据(Grafana、PostgreSQL)

运营

常用命令

# View logs (all services)
make docker-devnet-logs
# View logs (specific service)
docker compose -f docker-compose.devnet.yml --env-file versions.env --env-file .env.devnet logs -f indexer-solana
# Stop services
make docker-devnet-down
# Stop and wipe all state (volumes)
make docker-devnet-clean

可观测性

该服务栈包含 Prometheus、Grafana 和 cAdvisor,用于指标监控和容器监控。Grafana 可通过端口 37429 访问。

Grafana 的默认密码为 admin。在将端口 37429 暴露给 localhost 以外的任何网络之前,请务必更改此密码。

故障排除

存款后通道余额未更新

  1. 在主网浏览器上确认主网存款交易已成功上链
  2. 确认 indexer-solana 正在运行: docker compose -f docker-compose.devnet.yml --env-file versions.env --env-file .env.devnet logs -f indexer-solana
  3. 确认 operator-solana 正在运行: docker compose -f docker-compose.devnet.yml --env-file versions.env --env-file .env.devnet logs -f operator-solana
  4. 检查您的 Yellowstone gRPC 端点是否可访问,以及令牌是否有效 (DEVNET_YELLOWSTONE_ENDPOINT、INDEXER_YELLOWSTONE_TOKEN)
  5. 在链上确认后,等待最多 30 秒,因为 indexer 在记账前会应用最终性安全延迟

提款未结算至主网

  1. 确认 indexer-private-channel 正在运行: docker compose -f docker-compose.devnet.yml --env-file versions.env --env-file .env.devnet logs -f indexer-private-channel
  2. 确认 operator-private-channel 正在运行: docker compose -f docker-compose.devnet.yml --env-file versions.env --env-file .env.devnet logs -f operator-private-channel
  3. 确认 ADMIN_PRIVATE_KEY 中的运营商 keypair 与通过 AddOperator 在链上注册的密钥一致
  4. 如果日志显示「SMT root mismatch」,服务将主动关闭而非提交无效证明。请停止服务栈,从一致的状态恢复后重新启动

JWT 认证失败(所有请求均返回 401)

  1. 确认网关容器和认证服务容器上的 JWT_SECRET 完全一致
  2. 确认服务栈是以 --profile auth 启动的
  3. 令牌在 24 小时后过期;请重新认证以获取新令牌

首次构建耗时过长

这是正常现象。首次执行 make docker-devnet-build 需要编译所有 Rust 服务,在普通硬件上可能需要 30 至 60 分钟。后续构建将使用 Docker 层缓存,速度会显著加快。

后续步骤

Is this page helpful?

©️ 2026 Solana 基金会版权所有