Programmes précompilés

Résumé

Les précompilés (Ed25519, Secp256k1, Secp256r1) vérifient les signatures en tant que code natif, contournant la VM sBPF. Ils gèrent les opérations cryptographiques où l'exécution sBPF serait trop lente. Les précompilés ne sont pas appelables via CPI.

Programmes précompilés

Les programmes précompilés contournent la machine virtuelle sBPF et s'exécutent en tant que code natif au sein du validateur. Ils gèrent les opérations cryptographiques où l'exécution sBPF serait trop lente.

Vérifier la signature ed25519

Le programme ed25519 vérifie une ou plusieurs signatures ed25519 au sein d'une seule instruction.

ProgrammeID du programmeDescriptionInstructionsSource
Programme Ed25519Ed25519SigVerify111111111111111111111111111Vérifie les signatures ed25519. Si une signature échoue, une erreur est retournée.InstructionsSource

Le premier u8 de l'instruction contient un compteur du nombre de signatures à vérifier, suivi d'un seul octet de remplissage. Ensuite, la structure suivante est sérialisée une fois par signature :

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
}

Vérifier la récupération secp256k1

Le programme secp256k1 vérifie les opérations de récupération de clé publique secp256k1 (ecrecover).

ProgrammeID du programmeDescriptionInstructionsSource
Programme Secp256k1KeccakSecp256k11111111111111111111111111111Vérifie les opérations de récupération de clé publique secp256k1 (ecrecover).InstructionsSource

Le premier octet de l'instruction contient un compteur du nombre de clés publiques à vérifier. Ensuite, la structure suivante est sérialisée une fois par clé publique :

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 signature et les données du message peuvent référencer toutes les données d'instruction dans la transaction. En spécifiant le sysvar d'instructions spéciales, les programmes peuvent également lire les données de la transaction elle-même.

Le coût de la transaction est égal au nombre de signatures à vérifier multiplié par le coût de vérification par signature.

Vérifier la signature secp256r1

Le programme secp256r1 vérifie jusqu'à 8 signatures secp256r1 par instruction.

ProgrammeID du programmeDescriptionInstructionsSource
Programme Secp256r1Secp256r1SigVerify1111111111111111111111111Vérifie jusqu'à 8 signatures secp256r1. Prend une signature, une clé publique et un message. Renvoie une erreur en cas d'échec.InstructionsSource

Le premier u8 de l'instruction est un compteur de signatures à vérifier, suivi d'un seul octet de remplissage. Après cela, la structure suivante est sérialisée une fois par signature :

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
}

Les valeurs S basses sont imposées pour toutes les signatures afin d'éviter la malléabilité accidentelle des signatures.

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?

Table des matières

Modifier la page

Géré par

© 2026 Fondation Solana.
Tous droits réservés.
Restez connecté