Підсумок
Попередньо скомпільовані програми (Ed25519, Secp256k1, Secp256r1) перевіряють підписи як нативний код, обходячи віртуальну машину sBPF. Вони обробляють криптографічні операції, де виконання sBPF було б занадто повільним. Попередньо скомпільовані програми не можна викликати через CPI.
Попередньо скомпільовані програми
Попередньо скомпільовані програми обходять віртуальну машину sBPF і виконуються як нативний код всередині валідатора. Вони обробляють криптографічні операції, де виконання sBPF було б занадто повільним.
Перевірка підпису ed25519
Програма ed25519 перевіряє один або кілька підписів ed25519 в межах однієї інструкції.
| Програма | ID програми | Опис | Інструкції | Джерело |
|---|---|---|---|---|
| Програма Ed25519 | Ed25519SigVerify111111111111111111111111111 | Перевіряє підписи ed25519. Якщо будь-який підпис не пройде перевірку, повертається помилка. | Інструкції | Джерело |
Перший u8 інструкції містить кількість підписів для перевірки, за якою слідує
один байт заповнення. Після цього наступна структура серіалізується один раз для
кожного підпису:
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 у транзакції. Вказавши спеціальний sysvar інструкцій, програми також можуть зчитувати дані безпосередньо з самої транзакції.
Вартість транзакції дорівнює кількості підписів для перевірки, помноженій на вартість перевірки одного підпису.
Перевірка підпису secp256r1
Програма secp256r1 перевіряє до 8 підписів secp256r1 на одну інструкцію.
| Програма | ID програми | Опис | Інструкції | Джерело |
|---|---|---|---|---|
| Програма Secp256r1 | Secp256r1SigVerify1111111111111111111111111 | Перевіряє до 8 підписів secp256r1. Приймає підпис, публічний ключ та повідомлення. Повертає помилку, якщо будь-який не пройшов перевірку. | Інструкції | Джерело |
Перший u8 інструкції — це кількість підписів для перевірки, за якою слідує
один байт заповнення. Після цього наступна структура серіалізується один раз для
кожного підпису:
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?