Programy prekompilowane

Podsumowanie

Prekompilowane programy (Ed25519, Secp256k1, Secp256r1) weryfikują podpisy jako natywny kod, omijając maszynę wirtualną sBPF. Obsługują operacje kryptograficzne, w których wykonanie przez sBPF byłoby zbyt wolne. Prekompilowane programy nie są wywoływane przez CPI.

Programy prekompilowane

Programy prekompilowane omijają maszynę wirtualną sBPF i działają jako natywny kod w ramach validatora. Obsługują operacje kryptograficzne, w których wykonanie przez sBPF byłoby zbyt wolne.

Weryfikacja podpisu ed25519

Program ed25519 weryfikuje jeden lub więcej podpisów ed25519 w ramach jednej instrukcji.

ProgramID programuOpisInstrukcjeŹródło
Program Ed25519Ed25519SigVerify111111111111111111111111111Weryfikuje podpisy ed25519. Jeśli którykolwiek podpis jest niepoprawny, zwracany jest błąd.InstrukcjeŹródło

Pierwszy u8 instrukcji zawiera liczbę podpisów do sprawdzenia, po czym następuje jeden bajt wypełnienia. Następnie poniższa struktura jest serializowana raz dla każdego podpisu:

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
}

Weryfikacja odzyskiwania secp256k1

Program secp256k1 weryfikuje operacje odzyskiwania klucza publicznego secp256k1 (ecrecover).

ProgramID programuOpisInstrukcjeŹródło
Program Secp256k1KeccakSecp256k11111111111111111111111111111Weryfikuje operacje odzyskiwania klucza publicznego secp256k1 (ecrecover).InstrukcjeŹródło

Pierwszy bajt instrukcji zawiera liczbę kluczy publicznych do sprawdzenia. Następnie poniższa struktura jest serializowana raz dla każdego klucza publicznego:

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
}

Podpis i dane wiadomości mogą odwoływać się do dowolnych instruction data w transakcji. Poprzez określenie specjalnych instrukcji sysvar, programy mogą również odczytywać dane bezpośrednio z samej transakcji.

Koszt transakcji to liczba podpisów do weryfikacji pomnożona przez koszt weryfikacji pojedynczego podpisu.

Weryfikacja podpisu secp256r1

Program secp256r1 weryfikuje do 8 podpisów secp256r1 na jedną instrukcję.

ProgramProgram IDOpisInstrukcjeŹródło
Secp256r1 ProgramSecp256r1SigVerify1111111111111111111111111Weryfikuje do 8 podpisów secp256r1. Przyjmuje podpis, klucz publiczny i wiadomość. Zwraca błąd, jeśli którykolwiek podpis jest niepoprawny.InstrukcjeŹródło

Pierwszy u8 instrukcji to liczba podpisów do sprawdzenia, po której następuje pojedynczy bajt wypełnienia (padding). Następnie poniższa struktura jest serializowana raz dla każdego podpisu:

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
}

Niskie wartości S są wymuszane dla wszystkich podpisów, aby zapobiec przypadkowej modyfikowalności podpisu.

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?

Spis treści

Edytuj stronę

Zarządzane przez

© 2026 Solana Foundation.
Wszelkie prawa zastrzeżone.
Bądź na bieżąco