Programas pré-compilados

Resumo

Pré-compilados (Ed25519, Secp256k1, Secp256r1) verificam assinaturas como código nativo, contornando a VM sBPF. Eles lidam com operações criptográficas onde a execução sBPF seria demasiado lenta. Pré-compilados não são invocáveis via CPI.

Programas pré-compilados

Programas pré-compilados contornam a máquina virtual sBPF e são executados como código nativo dentro do validator. Eles lidam com operações criptográficas onde a execução sBPF seria demasiado lenta.

Verificar assinatura ed25519

O programa ed25519 verifica uma ou mais assinaturas ed25519 dentro de uma única instrução.

ProgramaID do programaDescriçãoInstruçõesFonte
Programa Ed25519Ed25519SigVerify111111111111111111111111111Verifica assinaturas ed25519. Se alguma assinatura falhar, um erro é retornado.InstruçõesFonte

O primeiro u8 da instrução contém uma contagem do número de assinaturas a verificar, seguido de um único byte de preenchimento. Após isso, a seguinte estrutura é serializada uma vez por assinatura:

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 recuperação secp256k1

O programa secp256k1 verifica operações de recuperação de chave pública secp256k1 (ecrecover).

ProgramaID do programaDescriçãoInstruçõesFonte
Programa Secp256k1KeccakSecp256k11111111111111111111111111111Verifica operações de recuperação de chave pública secp256k1 (ecrecover).InstruçõesFonte

O primeiro byte da instrução contém uma contagem do número de chaves públicas a verificar. Após isso, a seguinte estrutura é serializada uma vez por chave 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
}

Os dados de assinatura e mensagem podem referenciar quaisquer dados de instrução na transação. Ao especificar a sysvar de instruções especiais, os programas também podem ler dados da própria transação.

O custo da transação é igual ao número de assinaturas a verificar multiplicado pelo custo de verificação por assinatura.

Verificar assinatura secp256r1

O programa secp256r1 verifica até 8 assinaturas secp256r1 por instrução.

ProgramaID do programaDescriçãoInstruçõesFonte
Programa Secp256r1Secp256r1SigVerify1111111111111111111111111Verifica até 8 assinaturas secp256r1. Recebe uma assinatura, chave pública e mensagem. Retorna erro se alguma falhar.InstruçõesFonte

O primeiro u8 da instrução é uma contagem de assinaturas a verificar, seguido por um único byte de preenchimento. Depois disso, a seguinte estrutura é serializada uma vez por assinatura:

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
}

Valores S baixos são aplicados para todas as assinaturas para evitar maleabilidade acidental de assinatura.

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?

Índice

Editar Página

Gerenciado por

© 2026 Fundação Solana.
Todos os direitos reservados.
Conecte-se
  • Blog