Operadores

¿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:

  1. Indexar Mainnet para depósitos - indexer-solana monitorea Solana Mainnet en busca de eventos Deposit a través de Yellowstone gRPC; operator-solana recoge los depósitos confirmados y acuña el balance de tokens equivalente en la red del canal
  2. Indexar el canal para retiros - indexer-private-channel consulta el canal cada segundo en busca de eventos de quema WithdrawFunds y escribe los registros de retiro pendientes en la base de datos
  3. Liberar fondos en Mainnet - operator-private-channel recoge los registros pendientes y llama a ReleaseFunds en el Programa de Custodia con una prueba de exclusión SMT válida
  4. Gestionar la raíz SMT - operator-private-channel llama a ResetSmtRoot automáticamente cuando rotan los epoch del árbol; la verificación en cadena verify_smt_exclusion_proof es la última línea de defensa contra retiros no autorizados
  5. 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 service
AUTH_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.com
DEVNET_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-ui
pnpm install
echo "PRIVATE_CHANNEL_RPC_URL=http://localhost:8899" > .env
pnpm dev # opens at http://localhost:5173

Crear una instancia de custodia

  1. Configura tu wallet del navegador en Devnet y asegúrate de tener SOL de Devnet para las comisiones
  2. En el Admin UI, haz clic en Create New Instance y aprueba la transacción
  3. Copia la Instance Address y establécela como ESCROW_INSTANCE_ID en .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-passphrase
solana-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 AllowMint y 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:

  1. Allow Mint: Admin Functions -> Mint Management -> introduce la dirección del mint -> Allow Mint
  2. 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 services
make 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

  1. Confirma que la transacción de depósito en Mainnet se registró en un explorador de Mainnet
  2. Verifica que indexer-solana esté en ejecución: docker compose -f docker-compose.devnet.yml --env-file versions.env --env-file .env.devnet logs -f indexer-solana
  3. Verifica que operator-solana esté en ejecución: docker compose -f docker-compose.devnet.yml --env-file versions.env --env-file .env.devnet logs -f operator-solana
  4. Comprueba que tu endpoint de Yellowstone gRPC sea accesible y que el token sea válido (DEVNET_YELLOWSTONE_ENDPOINT, INDEXER_YELLOWSTONE_TOKEN)
  5. 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

  1. Verifica que indexer-private-channel esté en ejecución: docker compose -f docker-compose.devnet.yml --env-file versions.env --env-file .env.devnet logs -f indexer-private-channel
  2. Verifica que operator-private-channel esté en ejecución: docker compose -f docker-compose.devnet.yml --env-file versions.env --env-file .env.devnet logs -f operator-private-channel
  3. Confirma que el keypair del operador en ADMIN_PRIVATE_KEY coincide con la clave registrada con AddOperator en cadena
  4. 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)

  1. Confirma que JWT_SECRET es idéntico en los contenedores del gateway y del servicio de autenticación
  2. Confirma que el stack fue iniciado con --profile auth
  3. 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

Is this page helpful?