La firma parcial permite que varias partes firmen la misma transacción en momentos o dispositivos distintos. Un coordinador crea el mensaje, cada firmante requerido firma los bytes exactos del mensaje serializado, y el coordinador verifica y combina las firmas antes del envío.
Las firmas autorizan bytes, no intenciones
Cambiar el pagador de comisiones, el blockhash, el orden de las instrucciones, la lista de cuentas o cualquier instruction data genera un mensaje diferente e invalida todas las firmas ya recopiladas.
Flujo de firma parcial
- Acordar las instrucciones de la transacción y quién pagará la comisión.
- Establecer la vigencia de la transacción y el pagador de comisiones.
- Serializar el mensaje una sola vez. Tratar esos bytes como inmutables.
- Distribuir los bytes del mensaje y un resumen legible a cada firmante.
- Recopilar y verificar cada firma Ed25519 con los mismos bytes del mensaje.
- Asociar las firmas a las direcciones de los firmantes requeridos.
- Confirmar que todas las firmas requeridas están presentes y son válidas, y luego enviar.
Ejemplo completo
El pagador de comisiones y el remitente de SOL que aparecen a continuación firman de forma independiente. El coordinador verifica ambas firmas, las combina y envía la transacción completada.
El ejemplo utiliza firma Ed25519 en bruto para dejar explícito el límite entre el coordinador y cada firmante. Una billetera, un dispositivo de hardware, un servicio de custodia o un firmante sin conexión puede sustituir cualquiera de los keypair locales siempre que firme exactamente los mismos bytes del mensaje.
Congela el mensaje antes de firmar
Cada firma cubre el mensaje de transacción serializado. El mensaje incluye todo lo siguiente:
- el pagador de comisiones
- el blockhash reciente o el nonce duradero
- las direcciones de todos los programas y cuentas
- los permisos de firmante y de escritura de las cuentas
- el orden de las instrucciones y las instruction data
Define primero estos campos, serializa el mensaje una sola vez y distribuye ese arreglo de bytes a cada firmante. Es útil guardar un resumen (digest) del mensaje junto con cada solicitud de firma para que el coordinador pueda rechazar una firma devuelta para un mensaje diferente.
No deserialices un mensaje, lo modifiques y esperes que las firmas recopiladas previamente sigan siendo válidas. Incluso un cambio que parezca operativo, como reemplazar un blockhash vencido o cambiar el pagador de comisiones, exige que cada firmante vuelva a firmar.
Coordina el pagador de comisiones
El pagador de comisiones es siempre un firmante requerido y debe elegirse antes de que el mensaje se congele. Confirma que la cuenta tenga suficiente SOL para la comisión base y para cualquier comisión de prioridad. Si un patrocinador o un backend pagará la comisión, incluye esa dirección en el mensaje antes de recopilar la firma del usuario; agregar al patrocinador después cambia los bytes firmados.
El coordinador debe verificar que una firma entrante pertenezca a una dirección incluida como firmante requerido. Nunca aceptes una clave pública arbitraria ni la añadas a la transacción.
Gestiona la vigencia de la transacción
Una transacción con blockhash reciente solo es válida mientras su blockhash permanezca en la
cola de blockhashes recientes del validator. Antes de iniciar un flujo de firma entre varias partes,
estima si todos los firmantes pueden responder antes de lastValidBlockHeight.
Si el blockhash vence, crea un nuevo mensaje con un blockhash reciente y recopila todas las firmas de nuevo. Para flujos de trabajo que pueden tardar más o incluir firmantes sin conexión, utiliza un nonce duradero. Un nonce duradero evita la ventana del blockhash reciente, pero avanzar o consumir de otro modo ese nonce sigue invalidando la transacción pendiente.
Verifica antes del envío
Para cada firma devuelta:
- Verifica la firma con los bytes del mensaje congelado y la clave pública del firmante esperado.
- Asóciala a la posición de ese firmante en el arreglo de firmas de la transacción.
- Verifica que la transacción ensamblada tenga firmas válidas de todos los firmantes requeridos.
- Envía la transacción serializada sin reconstruir su mensaje.
Después del envío, confirma usando la misma información de vigencia que se incluyó en el mensaje firmado. Si la confirmación indica un blockhash vencido o un nonce consumido, no reintentes con una transacción modificada; reinicia el flujo de firma.
Is this page helpful?