¿Qué es un Operador de Private Channels?
Un operador es una entidad de confianza con permisos en cadena que sirve de puente entre Solana
Mainnet y la red de canales privados. Los operadores son aprovisionados por el
administrador de la instancia mediante AddOperator, que crea un PDA Operator en cadena;
sin esto, ninguna parte puede llamar a ReleaseFunds. En la práctica, un operador es una
organización o equipo que ejecuta los servicios encargados de monitorear depósitos, acuñar
tokens en el lado del canal, detectar retiros y liquidar fondos de vuelta a Mainnet.
Ejecutar una instancia ofrece a tus usuarios transferencias privadas de alto volumen que no
aparecen en Solana Mainnet, rendimiento instantáneo sin comisiones más allá del TPS nativo de Solana,
y acceso controlado mediante RBAC.
Si eres un desarrollador que integra una instancia de Private Channels existente en lugar de desplegar una, comienza con el Quickstart.
Antes de Comenzar
Requisitos Previos
Fija estas versiones en el host para que coincidan con las imágenes de Docker:
- Docker Engine 26+ (macOS Apple Silicon: habilita "Docker VMM" en Ajustes -> Virtual Machine Options)
- Node.js 24.7.0 y pnpm 10.15.1
- Solana CLI 3.1.13 (Agave)
- Rust 1.91.0
- Un endpoint de Yellowstone gRPC para Devnet (disponible en Helius, Triton, QuickNode)
Para los requisitos de red y la asignación de puertos predeterminada, consulta
docs/TECHNICAL_REQUIREMENTS.md
en el repositorio.
Instala el toolchain de Solana fijado y precalienta la caché SBF:
make install-toolchain
Servicios
Ejecutar una instancia de Private Channels implica asumir cinco responsabilidades continuas, cada una gestionada por contenedores dedicados en el stack de Docker Compose:
- Indexar Mainnet para depósitos -
indexer-solanamonitorea Solana Mainnet en busca de eventosDeposita través de Yellowstone gRPC;operator-solanarecoge los depósitos confirmados y acuña el balance de tokens equivalente en la red del canal - Indexar el canal para retiros -
indexer-private-channelconsulta el canal cada segundo en busca de eventos de quemaWithdrawFundsy escribe los registros de retiro pendientes en la base de datos - Liberar fondos en Mainnet -
operator-private-channelrecoge los registros pendientes y llama aReleaseFundsen el Programa de Custodia con una prueba de exclusión SMT válida - Gestionar la raíz SMT -
operator-private-channelllama aResetSmtRootautomáticamente cuando rotan los epoch del árbol; la verificación en cadenaverify_smt_exclusion_proofes la última línea de defensa contra retiros no autorizados - Ejecutar el gateway y el servicio de autenticación - el gateway es el único endpoint
público para todo el tráfico de clientes; el servicio de autenticación (opcional) aplica
JWT/RBAC cuando se establece
JWT_SECRET
Para el inventario completo de servicios y la asignación de puertos, consulta la Referencia de configuración.
Nota de seguridad: Los puertos de los nodos de escritura y lectura están vinculados únicamente al loopback (
127.0.0.1), pero varios otros servicios (gateway, auth, métricas del operador, Grafana, Prometheus, cAdvisor) se publican en todas las interfaces de red por defecto. Consulta la Referencia de configuración para ver la tabla de puertos completa y protege estos con un firewall antes de cualquier despliegue público. RBAC solo cubre los métodos JSON-RPC propios del gateway, no estos otros servicios.
Control de Acceso: Abierto vs. RBAC
Por defecto, el gateway acepta todas las conexiones sin necesidad de tokens. Para habilitar
RBAC basado en JWT, establece JWT_SECRET e inicia el stack con --profile auth. Consulta
Autenticación y Roles para la
referencia de configuración completa, incluido cómo aprovisionar el rol operator y
registrar las wallets de usuarios.
Si habilitas la autenticación, añade estos valores a tu entorno antes de iniciar el stack:
JWT_SECRET=<openssl rand -hex 32> # must match on gateway and auth serviceAUTH_PORT=8903
Configuración del Entorno
.env.devnet ya está rastreado en el repositorio con los valores predeterminados específicos de devnet
rellenos; edítalo directamente en lugar de regenerarlo desde .env.example,
lo que sobrescribiría esos valores predeterminados.
Completa los valores restantes a medida que avanzas por los pasos de despliegue a continuación; algunos
solo están disponibles durante el despliegue. Los secretos van en el archivo .env ignorado por git;
las variables no secretas van en .env.devnet.
Secretos - configúralos de inmediato:
POSTGRES_PASSWORD=<openssl rand -hex 32>POSTGRES_REPLICATION_PASSWORD=<openssl rand -hex 32>
Variables obtenidas durante el despliegue:
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.comDEVNET_YELLOWSTONE_ENDPOINT=<your Yellowstone gRPC endpoint>INDEXER_YELLOWSTONE_TOKEN=<your Yellowstone auth token>
ADMIN_PRIVATE_KEY es el firmante pagador de comisiones propio y requerido de los servicios fuera de cadena,
sin relación con el administrador de la instancia en cadena del Paso 3. Esta guía coloca el
keypair del operador generado en el Paso 4 a continuación en ADMIN_PRIVATE_KEY y
deja el OPERATOR_PRIVATE_KEY opcional sin establecer, de modo que el firmante del operador
recurre a la misma clave. Nunca introduzcas el keypair del administrador de instancia a nivel de protocolo del
Paso 3 en ninguna de las dos variables.
Para la referencia completa de variables de entorno, consulta Configuración.
Despliegue
Compilar imágenes
make docker-devnet-build
Esto compila todos los servicios de Rust en una imagen de Docker compartida. La primera compilación tarda entre 30 minutos y una hora.
Configurar el Admin UI
El Admin UI es una herramienta basada en navegador para crear y configurar la instancia de custodia:
una utilidad de desarrollo y administración, no un producto orientado al usuario
ni un componente de tiempo de ejecución obligatorio. Todas las operaciones que realiza
(CreateInstance, AllowMint, AddOperator) también pueden ejecutarse mediante los scripts CLI
del repositorio.
cd admin-uipnpm installecho "PRIVATE_CHANNEL_RPC_URL=http://localhost:8899" > .envpnpm dev # opens at http://localhost:5173
Crear una instancia de custodia
- Configura tu wallet del navegador en Devnet y asegúrate de tener SOL de Devnet para las comisiones
- En el Admin UI, haz clic en Create New Instance y aprueba la transacción
- Copia la Instance Address y establécela como
ESCROW_INSTANCE_IDen.env.devnet
Alternativamente, usa el script CLI:
cargo run --bin create_instance -- https://api.devnet.solana.com ./keypairs/admin.json
Generar un keypair de operador
solana-keygen new -o operator-keypair.json -s --no-bip39-passphrasesolana-keygen pubkey operator-keypair.json
Establece el contenido del keypair como ADMIN_PRIVATE_KEY en tu entorno. La clave pública
no es una variable de entorno; la pasarás directamente como el pubkey del operador
en el paso "Configurar la instancia" a continuación.
Finalizar las variables de entorno
Actualiza .env.devnet con ESCROW_INSTANCE_ID, DEVNET_RPC_URL,
DEVNET_YELLOWSTONE_ENDPOINT e INDEXER_YELLOWSTONE_TOKEN. Coloca los secretos
(POSTGRES_PASSWORD, POSTGRES_REPLICATION_PASSWORD, ADMIN_PRIVATE_KEY) en
el archivo .env ignorado por git.
Si decidiste habilitar RBAC
(Control de Acceso: Abierto vs. RBAC), añade también
JWT_SECRET y AUTH_PORT ahora.
Iniciar todos los servicios
Sin autenticación:
make docker-devnet-up
Con autenticación:
docker compose -f docker-compose.devnet.yml --env-file versions.env --env-file .env.devnet --env-file .env --profile auth up -d
Compose deshabilita la carga automática de .env una vez que se pasa cualquier flag --env-file,
por lo que el --env-file .env al final es obligatorio. Sin él,
POSTGRES_PASSWORD, ADMIN_PRIVATE_KEY y JWT_SECRET (que colocaste en
.env arriba) se resuelven vacíos y el stack no arranca correctamente.
Inicia los servicios antes de configurar la instancia. El indexer transmite eventos en tiempo real, por lo que levantar el stack primero garantiza que
AllowMinty tu primer depósito se indexen en orden sin necesidad de un relleno retroactivo.
Configurar la instancia
Con el stack en ejecución, añade a la lista blanca un mint de token y agrega tu operador a través del Admin UI:
- Allow Mint: Admin Functions -> Mint Management -> introduce la dirección del mint -> Allow Mint
- Add Operator: Admin Functions -> Operator Management -> introduce el pubkey del operador -> Add Operator
O mediante CLI:
cargo run --bin add_operator -- \https://api.devnet.solana.com \./keypairs/admin.json \<INSTANCE_ID> \<OPERATOR_PUBKEY>
Esta guía apunta a la devnet de Solana. Para Mainnet:
- Los IDs de programa se compilan mediante
declare_id!(): verifica que estás usando los IDs de Mainnet correctos del repositorio - Los endpoints de Yellowstone gRPC requieren un plan de Mainnet; los endpoints de devnet no transmitirán eventos de Mainnet
- La wallet del operador paga comisiones en SOL por cada llamada a
ReleaseFunds, así que dimensiona el saldo de SOL según tu volumen esperado de retiros - Cambia todas las credenciales predeterminadas (Grafana, PostgreSQL) antes de cualquier despliegue público
Operaciones
Comandos Útiles
# 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 servicesmake docker-devnet-down# Stop and wipe all state (volumes)make docker-devnet-clean
Observabilidad
El stack incluye Prometheus, Grafana y cAdvisor para métricas y monitoreo de contenedores.
Grafana es accesible en el puerto 37429.
La contraseña predeterminada de Grafana es admin. Cámbiala antes de exponer el puerto 37429
a cualquier red más allá de localhost.
Solución de Problemas
El balance del canal no se actualiza tras el depósito
- Confirma que la transacción de depósito en Mainnet se registró en un explorador de Mainnet
- Verifica que
indexer-solanaesté en ejecución:docker compose -f docker-compose.devnet.yml --env-file versions.env --env-file .env.devnet logs -f indexer-solana - Verifica que
operator-solanaesté en ejecución:docker compose -f docker-compose.devnet.yml --env-file versions.env --env-file .env.devnet logs -f operator-solana - Comprueba que tu endpoint de Yellowstone gRPC sea accesible y que el token sea válido
(
DEVNET_YELLOWSTONE_ENDPOINT,INDEXER_YELLOWSTONE_TOKEN) - Espera hasta 30 segundos tras la confirmación en cadena, ya que el indexer aplica un retraso de seguridad de finalidad antes de acreditar
El retiro no se liquida en Mainnet
- Verifica que
indexer-private-channelesté en ejecución:docker compose -f docker-compose.devnet.yml --env-file versions.env --env-file .env.devnet logs -f indexer-private-channel - Verifica que
operator-private-channelesté en ejecución:docker compose -f docker-compose.devnet.yml --env-file versions.env --env-file .env.devnet logs -f operator-private-channel - Confirma que el keypair del operador en
ADMIN_PRIVATE_KEYcoincide con la clave registrada conAddOperatoren cadena - Si los registros muestran "SMT root mismatch", el servicio se detiene en lugar de enviar una prueba inválida. Detén el stack, restaura desde un estado consistente y reinicia
Fallos de autenticación JWT (401 en todas las solicitudes)
- Confirma que
JWT_SECRETes idéntico en los contenedores del gateway y del servicio de autenticación - Confirma que el stack fue iniciado con
--profile auth - Los tokens expiran después de 24 horas; vuelve a autenticarte para obtener un token nuevo
La primera compilación tarda demasiado
Es lo esperado. El primer make docker-devnet-build compila todos los servicios de Rust y
puede tardar entre 30 y 60 minutos en hardware típico. Las compilaciones posteriores utilizan la caché de
capas de Docker y son significativamente más rápidas.
Próximos Pasos
Quickstart
Prueba tu despliegue: deposita, transfiere y retira en devnet.
Configuración
Referencia completa de variables de entorno para todos los servicios.
Autenticación y Roles
Configure la autenticación JWT y aprovisione usuarios con rol de operador.
Instrucciones
Referencia completa de todas las instrucciones en cadena.
Is this page helpful?