Ciclo de vida de las claves y flujo de firma
Keygen, firma y resharing desde el lado del cosigner.
Keygen
Crear una billetera en un workspace con un cosigner ejecuta la generación distribuida de claves entre los nodos de MPCium y tu cosigner.
- El orquestador envía un
session_startfirmado conKEYGEN, elkey_id, el protocolo y el umbral. - El cosigner verifica la firma y consulta a tu callback.
- Los participantes ejecutan el keygen de tss-lib. Cada uno termina con su propio fragmento y la clave pública compartida.
- El cosigner cifra su fragmento, lo almacena como
shares:<protocol>:<key_id>y registra el comité. - Solo la clave pública y un hash del resultado salen del cosigner.
- El orquestador comprueba que todas las claves públicas coincidan y las devuelve a Apex.
Las billeteras que necesitan tanto ECDSA como EdDSA ejecutan dos sesiones vinculadas. Si una falla, ambas se abortan.
ECDSA necesita preparámetros de Paillier. El cosigner los genera en el primer arranque (hasta 5 minutos) e informa que no está listo hasta terminar.
Firma

1. Admisión
Una solicitud que supera las políticas de tu workspace pasa de Apex al orquestador, firmada con la clave de iniciador de Apex. El orquestador compara el comité con el registro del keygen, confirma que todos estén en línea y envía un session_start firmado.
session_start incluye el key_id, el signing_input sin procesar, un signing_context opcional (detalles de la transacción, máximo 64 KiB), la derivation HD, el umbral y los participantes.
2. Controles locales
El cosigner rechaza la sesión a menos que se superen todos estos controles, en orden:
- Mensaje de menos de 128 KiB.
- Firma del orquestador válida (clave fijada durante el emparejamiento).
- Menos de 20 inicios y 10 abortos por minuto.
- Menos de 5 sesiones simultáneas.
session_startescrito en el registro de auditoría.- Tu callback devuelve
approve. De lo contrario, la sesión falla conCALLBACK_REJECTED.
Si el orquestador aborta mientras el callback está pendiente, el cosigner deja de esperar.
3. Intercambio de claves
- La sesión debe coincidir con el comité fijado: umbral, claves de las partes, claves de identidad y flags de aprobador.
- El cosigner envía
peer_joined,peer_readyy una clave X25519 firmada a cada peer. - Cada par de peers obtiene una clave ChaCha20-Poly1305 por dirección (HKDF sobre X25519, vinculada a la sesión).
4. Firma de umbral
El orquestador envía mpc_begin. Si la billetera tiene un aprobador (por ejemplo, un aprobador móvil de Fystack), mpc_begin debe incluir su aprobación firmada de este signing input exacto. Sin ella, el cosigner hace fallar la sesión con APPROVAL_REQUIRED.
Luego, los participantes ejecutan las rondas de tss-lib. Cada mensaje está firmado y numerado en secuencia, por lo que se descartan los reenvíos.
5. Resultado
Cada participante informa un hash de su firma. El orquestador exige que todos los hashes coincidan y luego devuelve el resultado firmado (signature, r, s, recovery id) a Apex. El cosigner registra session_end y elimina su checkpoint.
Resharing
Reemplaza los fragmentos, opcionalmente con un nuevo comité o umbral. La clave pública y las direcciones no cambian.
- El comité y el umbral anteriores provienen del registro del keygen, no de quien hace la llamada.
- Al menos
threshold + 1miembros anteriores deben estar en línea. - Los miembros anteriores y nuevos ejecutan el resharing de tss-lib. Los fragmentos nuevos quedan preparados; los anteriores siguen activos.
- Todos los participantes informan el mismo resultado y una clave pública sin cambios.
- El orquestador persiste la decisión y luego envía un
reshare_commitfirmado. Cada participante reemplaza su fragmento por el nuevo.
Abortar antes del commit conserva los fragmentos anteriores. Después del commit solo se avanza: el commit se reintenta hasta que todos los participantes lo confirmen, incluso después de una caída.
El resharing se habilita por despliegue. Contacta a Fystack antes de cambiar un comité.
Códigos de error
| Código | Significado |
|---|---|
CALLBACK_REJECTED |
El callback rechazó la solicitud, agotó el tiempo de espera o devolvió una respuesta inválida. |
APPROVAL_REQUIRED |
Falta la aprobación firmada del aprobador de la billetera. |
UNAVAILABLE |
Un participante estaba desconectado al enviar la solicitud. |
PARTICIPANT_FAILED |
Un participante informó un error. Consulta failure_reason. |
PARTICIPANT_DISCONNECTED |
El stream de un participante se cortó a mitad de la sesión. |
SESSION_TIMEOUT |
No se completó en 120 segundos. |
RESULT_HASH_MISMATCH |
Los participantes no coincidieron en el resultado. |
CONFLICT |
Hay otra sesión en curso para esta billetera y protocolo. |