사전 컴파일된 프로그램

요약

사전 컴파일(Ed25519, Secp256k1, Secp256r1)은 sBPF VM을 우회하여 네이티브 코드로 서명을 검증합니다. sBPF 실행이 너무 느린 암호화 작업을 처리합니다. 사전 컴파일은 CPI를 통해 호출할 수 없습니다.

사전 컴파일된 프로그램

사전 컴파일된 프로그램은 sBPF 가상 머신을 우회하고 validator 내에서 네이티브 코드로 실행됩니다. sBPF 실행이 너무 느린 암호화 작업을 처리합니다.

ed25519 서명 검증

ed25519 프로그램은 단일 명령어 내에서 하나 이상의 ed25519 서명을 검증합니다.

프로그램프로그램 ID설명명령어소스
Ed25519 프로그램Ed25519SigVerify111111111111111111111111111ed25519 서명을 검증합니다. 서명이 실패하면 오류가 반환됩니다.명령어소스

명령어의 첫 번째 u8에는 확인할 서명 수가 포함되며, 그 뒤에 1바이트의 패딩이 있습니다. 그 후, 다음 구조체가 서명당 한 번씩 직렬화됩니다:

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
}

secp256k1 복구 검증

secp256k1 프로그램은 secp256k1 공개 키 복구 작업(ecrecover)을 검증합니다.

프로그램프로그램 ID설명명령어소스
Secp256k1 프로그램KeccakSecp256k11111111111111111111111111111secp256k1 공개 키 복구 작업(ecrecover)을 검증합니다.명령어소스

명령어의 첫 번째 바이트에는 확인할 공개 키 수가 포함됩니다. 그 후, 다음 구조체가 공개 키당 한 번씩 직렬화됩니다:

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
}

서명 및 메시지 데이터는 트랜잭션 내의 모든 instruction data를 참조할 수 있습니다. 특수 instructions sysvar를 지정하면 프로그램이 트랜잭션 자체에서 데이터를 읽을 수도 있습니다.

트랜잭션 비용은 검증할 서명 수에 서명당 검증 비용을 곱한 값과 같습니다.

secp256r1 서명 검증

secp256r1 프로그램은 instruction당 최대 8개의 secp256r1 서명을 검증합니다.

프로그램프로그램 ID설명Instructions소스
Secp256r1 프로그램Secp256r1SigVerify1111111111111111111111111최대 8개의 secp256r1 서명을 검증합니다. 서명, 공개 키 및 메시지를 받아 실패 시 오류를 반환합니다.Instructions소스

instruction의 첫 번째 u8는 확인할 서명 수이며, 그 뒤에 1바이트의 패딩이 옵니다. 그 후 다음 구조체가 서명당 한 번씩 직렬화됩니다:

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
}

우발적인 서명 변조 가능성을 방지하기 위해 모든 서명에 대해 낮은 S 값이 적용됩니다.

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?

목차

페이지 편집

관리자

© 2026 솔라나 재단.
모든 권리 보유.
연결하기