Resumen
Los precompilados (Ed25519, Secp256k1, Secp256r1) verifican firmas como código nativo, evitando la VM sBPF. Manejan operaciones criptográficas donde la ejecución sBPF sería demasiado lenta. Los precompilados no son invocables mediante CPI.
Programas precompilados
Los programas precompilados evitan la máquina virtual sBPF y se ejecutan como código nativo dentro del validador. Manejan operaciones criptográficas donde la ejecución sBPF sería demasiado lenta.
Verificar firma ed25519
El programa ed25519 verifica una o más firmas ed25519 dentro de una única instrucción.
| Programa | ID del programa | Descripción | Instrucciones | Fuente |
|---|---|---|---|---|
| Programa Ed25519 | Ed25519SigVerify111111111111111111111111111 | Verifica firmas ed25519. Si alguna firma falla, se devuelve un error. | Instrucciones | Fuente |
El primer u8 de la instrucción contiene un recuento del número de firmas a
verificar, seguido de un solo byte de relleno. Después de eso, la siguiente
estructura se serializa una vez por firma:
struct Ed25519SignatureOffsets {signature_offset: u16, // offset to ed25519 signature of 64 bytessignature_instruction_index: u16, // instruction index to find signaturepublic_key_offset: u16, // offset to public key of 32 bytespublic_key_instruction_index: u16, // instruction index to find public keymessage_data_offset: u16, // offset to start of message datamessage_data_size: u16, // size of message datamessage_instruction_index: u16, // index of instruction data to get message data}
process_instruction() {for i in 0..count {// i'th index values referenced:instructions = &transaction.message().instructionsinstruction_index = ed25519_signature_instruction_index != u16::MAX ? ed25519_signature_instruction_index : current_instruction;signature = instructions[instruction_index].data[ed25519_signature_offset..ed25519_signature_offset + 64]instruction_index = ed25519_pubkey_instruction_index != u16::MAX ? ed25519_pubkey_instruction_index : current_instruction;pubkey = instructions[instruction_index].data[ed25519_pubkey_offset..ed25519_pubkey_offset + 32]instruction_index = ed25519_message_instruction_index != u16::MAX ? ed25519_message_instruction_index : current_instruction;message = instructions[instruction_index].data[ed25519_message_data_offset..ed25519_message_data_offset + ed25519_message_data_size]if pubkey.verify(signature, message) != Success {return Error}}return Success}
Verificar recuperación secp256k1
El programa secp256k1 verifica operaciones de recuperación de clave pública secp256k1 (ecrecover).
| Programa | ID del programa | Descripción | Instrucciones | Fuente |
|---|---|---|---|---|
| Programa Secp256k1 | KeccakSecp256k11111111111111111111111111111 | Verifica operaciones de recuperación de clave pública secp256k1 (ecrecover). | Instrucciones | Fuente |
El primer byte de la instrucción contiene un recuento del número de claves públicas a verificar. Después de eso, la siguiente estructura se serializa una vez por clave pública:
struct SecpSignatureOffsets {signature_offset: u16, // offset to [signature,recovery_id] of 64+1 bytessignature_instruction_index: u8, // instruction index to find signatureeth_address_offset: u16, // offset to ethereum_address of 20 byteseth_address_instruction_index: u8, // instruction index to find ethereum addressmessage_data_offset: u16, // offset to start of message datamessage_data_size: u16, // size of message datamessage_instruction_index: u8, // instruction index to find message data}
process_instruction() {for i in 0..count {// i'th index values referenced:instructions = &transaction.message().instructionssignature = instructions[signature_instruction_index].data[signature_offset..signature_offset + 64]recovery_id = instructions[signature_instruction_index].data[signature_offset + 64]ref_eth_pubkey = instructions[eth_address_instruction_index].data[eth_address_offset..eth_address_offset + 20]message_hash = keccak256(instructions[message_instruction_index].data[message_data_offset..message_data_offset + message_data_size])pubkey = ecrecover(signature, recovery_id, message_hash)eth_pubkey = keccak256(pubkey[1..])[12..]if eth_pubkey != ref_eth_pubkey {return Error}}return Success}
La firma y los datos del mensaje pueden hacer referencia a cualquier dato de instrucción en la transacción. Al especificar el sysvar de instrucciones especiales, los programas también pueden leer datos de la propia transacción.
El costo de la transacción es igual al número de firmas a verificar multiplicado por el costo de verificación por firma.
Verificar firma secp256r1
El programa secp256r1 verifica hasta 8 firmas secp256r1 por instrucción.
| Programa | ID del programa | Descripción | Instrucciones | Fuente |
|---|---|---|---|---|
| Programa Secp256r1 | Secp256r1SigVerify1111111111111111111111111 | Verifica hasta 8 firmas secp256r1. Toma una firma, clave pública y mensaje. Devuelve error si alguna falla. | Instrucciones | Fuente |
El primer u8 de la instrucción es un recuento de firmas a verificar, seguido
de un solo byte de relleno. Después de eso, la siguiente estructura se serializa
una vez por firma:
struct Secp256r1SignatureOffsets {signature_offset: u16, // offset to compact secp256r1 signature of 64 bytessignature_instruction_index: u16, // instruction index to find signaturepublic_key_offset: u16, // offset to compressed public key of 33 bytespublic_key_instruction_index: u16, // instruction index to find public keymessage_data_offset: u16, // offset to start of message datamessage_data_size: u16, // size of message datamessage_instruction_index: u16, // index of instruction data to get message data}
Se aplican valores S bajos para todas las firmas para evitar la maleabilidad accidental de firmas.
process_instruction() {if data.len() < SIGNATURE_OFFSETS_START {return Error}num_signatures = data[0] as usizeif num_signatures == 0 || num_signatures > 8 {return Error}expected_data_size = num_signatures * SIGNATURE_OFFSETS_SERIALIZED_SIZE + SIGNATURE_OFFSETS_STARTif data.len() < expected_data_size {return Error}for i in 0..num_signatures {offsets = parse_signature_offsets(data, i)signature = get_data_slice(data, instruction_datas, offsets.signature_instruction_index, offsets.signature_offset, SIGNATURE_SERIALIZED_SIZE)if s > half_curve_order {return Error}pubkey = get_data_slice(data, instruction_datas, offsets.public_key_instruction_index, offsets.public_key_offset, COMPRESSED_PUBKEY_SERIALIZED_SIZE)message = get_data_slice(data, instruction_datas, offsets.message_instruction_index, offsets.message_data_offset, offsets.message_data_size)if !verify_signature(signature, pubkey, message) {return Error}}return Success}
Is this page helpful?