Arquitectura de Cosigner
Qué se ejecuta dónde, cómo se comunican las partes y cómo se coordina una sesión.

Componentes
Runtime de Cosigner
Un único binario de Go, distribuido como ghcr.io/fystack/cosigner para linux/amd64 y linux/arm64. Se une a las sesiones, pero no las coordina.
- Motor MPC: el fork de Fystack de tss-lib, igual que MPCium. ECDSA usa GG18 sobre secp256k1. EdDSA usa Ed25519 de umbral de tss-lib.
- Clave de identidad: Ed25519, creada durante el emparejamiento. Autentica al Cosigner y firma sus mensajes.
- Almacén de claves: filas cifradas con AES-256-GCM en SQLite (predeterminado), Badger o DynamoDB.
- Relay del Gateway: un único stream gRPC saliente. Envía señales de presencia cada 5 segundos.
- Cliente de aprobación: llama a tu callback de aprobación antes de cada sesión.
- Registro de auditoría: JSONL firmado y encadenado por hash.
Tus servicios
- cosigner-cli: instala, verifica, empareja, inicia y respalda el runtime.
- Callback de aprobación: tu servidor HTTPS. Devuelve
approveoreject. - Origen de la clave de almacenamiento: una contraseña (perfil
manual) o AWS KMS (perfilunattended).
Servicios de Fystack
- Apex: emite tokens de emparejamiento, registra las claves de los Cosigners, gestiona la revocación y envía solicitudes MPC.
- Gateway: acepta los streams de los Cosigners, verifica la identidad y la revocación, y enruta el tráfico hacia NATS. Un único stream activo por Cosigner entre todas las réplicas.
- Orchestrator: ejecuta la máquina de estados de las sesiones y firma cada mensaje de control. Nunca toca los fragmentos de clave.
- MPCium: los nodos MPC de Fystack. Consulta MPCium.
Canales
| Origen → destino | Transporte | Autenticación | Contenido |
|---|---|---|---|
| Cosigner → Apex | HTTPS | Token de emparejamiento de un solo uso | Registro de identidad |
| Cosigner ↔ Gateway | gRPC stream, TLS | JWT EdDSA, vigencia de 60 s | Todo el tráfico de la sesión |
| Gateway ↔ Orchestrator ↔ MPCium | NATS | Ed25519 por mensaje | Coordinación dentro de Fystack |
| Participante ↔ participante | Retransmitido | X25519 + ChaCha20-Poly1305 | Rondas MPC, cifradas de extremo a extremo |
| Cosigner → Callback | HTTPS | JWT RS256 en ambos sentidos | Aprobar o rechazar |
Sobres del stream
Cada trama lleva los valores autenticados de workspace_id, cosigner_id y participant_id. El Gateway descarta las tramas que no coinciden con la identidad del stream.
| Tipo | Dirección | Subject |
|---|---|---|
CONTROL |
Orchestrator → cosigner | mpc.v1.peer.<participant_id>.control |
SESSION_EVENT |
Cosigner → orchestrator | mpc.v1.session.<session_id>.event |
P2P |
Participante ↔ participante | mpc.v1.peer.<to>.session.<session_id>.p2p |
PRESENCE |
Cosigner → orchestrator | mpc.v1.peer.<participant_id>.presence |
Límites de confianza
- Gateway: retransmite texto cifrado. Puede descartar o retrasar tráfico, pero no puede leer ni falsificar mensajes MPC.
- Orchestrator: firma cada mensaje de control con una clave que el Cosigner fijó durante el emparejamiento. Los mensajes sin firma o mal firmados se descartan.
- Apex: no puede omitir tu callback. Cada sesión pasa primero por tu callback.
- Tu Cosigner: no puede firmar solo. El comité queda fijado en la generación de claves.
Más detalles en Modelo de seguridad.
Sesiones
Cada generación de claves, firma o recompartición es una sesión del orchestrator con un TTL de 120 segundos.

- Admisión: el Orchestrator verifica la firma de Apex, comprueba el comité y confirma que todos los participantes estén en línea. Solo una sesión por billetera y protocolo a la vez.
- waiting: los participantes reciben un
session_startfirmado, ejecutan comprobaciones locales (el Cosigner llama a tu callback) y respondenpeer_joined,peer_ready. - key_exchange: los participantes intercambian claves X25519 firmadas. Las billeteras con un aprobador también necesitan aquí su aprobación firmada.
- active_mpc: el Orchestrator envía
mpc_begin. Los participantes ejecutan directamente las rondas de tss-lib. - completed: todos los participantes informan el mismo hash de resultado. El Orchestrator firma y publica el resultado.
Una sesión falla ante un error de un participante, una desconexión o resultados que no coinciden, y expira después de 120 segundos. En ambos casos, el orchestrator difunde un session_abort firmado.
Comités
Un umbral t significa t + 1 firmantes (semántica de tss-lib). El comité de nodos MPCium y Cosigners queda fijado en la generación de claves. Toda sesión posterior debe usar las mismas claves de las partes, claves de identidad y roles de aprobador.
Conexiones
- Un único stream activo por identidad de Cosigner. Una segunda instancia con la misma identidad se rechaza.
- Cada sesión queda vinculada al stream que estaba activo cuando se inició. Si ese stream se cae, la sesión falla con
PARTICIPANT_DISCONNECTED. - Un Cosigner revocado recibe
PermissionDeniedy se detiene.