요약
사전 컴파일(Ed25519, Secp256k1, Secp256r1)은 sBPF VM을 우회하여 네이티브 코드로 서명을 검증합니다. sBPF 실행이 너무 느린 암호화 작업을 처리합니다. 사전 컴파일은 CPI를 통해 호출할 수 없습니다.
사전 컴파일된 프로그램
사전 컴파일된 프로그램은 sBPF 가상 머신을 우회하고 validator 내에서 네이티브 코드로 실행됩니다. sBPF 실행이 너무 느린 암호화 작업을 처리합니다.
ed25519 서명 검증
ed25519 프로그램은 단일 명령어 내에서 하나 이상의 ed25519 서명을 검증합니다.
| 프로그램 | 프로그램 ID | 설명 | 명령어 | 소스 |
|---|---|---|---|---|
| Ed25519 프로그램 | Ed25519SigVerify111111111111111111111111111 | ed25519 서명을 검증합니다. 서명이 실패하면 오류가 반환됩니다. | 명령어 | 소스 |
명령어의 첫 번째 u8에는 확인할 서명 수가 포함되며, 그 뒤에 1바이트의 패딩이
있습니다. 그 후, 다음 구조체가 서명당 한 번씩 직렬화됩니다:
struct Ed25519SignatureOffsets {signature_offset: u16, // offset to ed25519 signature of 64 bytessignature_instruction_index: u16, // instruction index to find signaturepublic_key_offset: u16, // offset to public key of 32 bytespublic_key_instruction_index: u16, // instruction index to find public keymessage_data_offset: u16, // offset to start of message datamessage_data_size: u16, // size of message datamessage_instruction_index: u16, // index of instruction data to get message data}
process_instruction() {for i in 0..count {// i'th index values referenced:instructions = &transaction.message().instructionsinstruction_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 프로그램 | KeccakSecp256k11111111111111111111111111111 | secp256k1 공개 키 복구 작업(ecrecover)을 검증합니다. | 명령어 | 소스 |
명령어의 첫 번째 바이트에는 확인할 공개 키 수가 포함됩니다. 그 후, 다음 구조체가 공개 키당 한 번씩 직렬화됩니다:
struct SecpSignatureOffsets {signature_offset: u16, // offset to [signature,recovery_id] of 64+1 bytessignature_instruction_index: u8, // instruction index to find signatureeth_address_offset: u16, // offset to ethereum_address of 20 byteseth_address_instruction_index: u8, // instruction index to find ethereum addressmessage_data_offset: u16, // offset to start of message datamessage_data_size: u16, // size of message datamessage_instruction_index: u8, // instruction index to find message data}
process_instruction() {for i in 0..count {// i'th index values referenced:instructions = &transaction.message().instructionssignature = 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바이트의 패딩이
옵니다. 그 후 다음 구조체가 서명당 한 번씩 직렬화됩니다:
struct Secp256r1SignatureOffsets {signature_offset: u16, // offset to compact secp256r1 signature of 64 bytessignature_instruction_index: u16, // instruction index to find signaturepublic_key_offset: u16, // offset to compressed public key of 33 bytespublic_key_instruction_index: u16, // instruction index to find public keymessage_data_offset: u16, // offset to start of message datamessage_data_size: u16, // size of message datamessage_instruction_index: u16, // index of instruction data to get message data}
우발적인 서명 변조 가능성을 방지하기 위해 모든 서명에 대해 낮은 S 값이 적용됩니다.
process_instruction() {if data.len() < SIGNATURE_OFFSETS_START {return Error}num_signatures = data[0] as usizeif num_signatures == 0 || num_signatures > 8 {return Error}expected_data_size = num_signatures * SIGNATURE_OFFSETS_SERIALIZED_SIZE + SIGNATURE_OFFSETS_STARTif 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?