Programas precompilados

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.

ProgramaID del programaDescripciónInstruccionesFuente
Programa Ed25519Ed25519SigVerify111111111111111111111111111Verifica firmas ed25519. Si alguna firma falla, se devuelve un error.InstruccionesFuente

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:

Ed25519SignatureOffsets
struct Ed25519SignatureOffsets {
signature_offset: u16, // offset to ed25519 signature of 64 bytes
signature_instruction_index: u16, // instruction index to find signature
public_key_offset: u16, // offset to public key of 32 bytes
public_key_instruction_index: u16, // instruction index to find public key
message_data_offset: u16, // offset to start of message data
message_data_size: u16, // size of message data
message_instruction_index: u16, // index of instruction data to get message data
}
Signature verification pseudocode
process_instruction() {
for i in 0..count {
// i'th index values referenced:
instructions = &transaction.message().instructions
instruction_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).

ProgramaID del programaDescripciónInstruccionesFuente
Programa Secp256k1KeccakSecp256k11111111111111111111111111111Verifica operaciones de recuperación de clave pública secp256k1 (ecrecover).InstruccionesFuente

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:

SecpSignatureOffsets
struct SecpSignatureOffsets {
signature_offset: u16, // offset to [signature,recovery_id] of 64+1 bytes
signature_instruction_index: u8, // instruction index to find signature
eth_address_offset: u16, // offset to ethereum_address of 20 bytes
eth_address_instruction_index: u8, // instruction index to find ethereum address
message_data_offset: u16, // offset to start of message data
message_data_size: u16, // size of message data
message_instruction_index: u8, // instruction index to find message data
}
Recovery verification pseudocode
process_instruction() {
for i in 0..count {
// i'th index values referenced:
instructions = &transaction.message().instructions
signature = 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.

ProgramaID del programaDescripciónInstruccionesFuente
Programa Secp256r1Secp256r1SigVerify1111111111111111111111111Verifica hasta 8 firmas secp256r1. Toma una firma, clave pública y mensaje. Devuelve error si alguna falla.InstruccionesFuente

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:

Secp256r1SignatureOffsets
struct Secp256r1SignatureOffsets {
signature_offset: u16, // offset to compact secp256r1 signature of 64 bytes
signature_instruction_index: u16, // instruction index to find signature
public_key_offset: u16, // offset to compressed public key of 33 bytes
public_key_instruction_index: u16, // instruction index to find public key
message_data_offset: u16, // offset to start of message data
message_data_size: u16, // size of message data
message_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.

Signature verification pseudocode
process_instruction() {
if data.len() < SIGNATURE_OFFSETS_START {
return Error
}
num_signatures = data[0] as usize
if num_signatures == 0 || num_signatures > 8 {
return Error
}
expected_data_size = num_signatures * SIGNATURE_OFFSETS_SERIALIZED_SIZE + SIGNATURE_OFFSETS_START
if 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?

Tabla de Contenidos

Editar Página

Gestionado por

© 2026 Fundación Solana.
Todos los derechos reservados.
Conéctate