概要
プリコンパイル(Ed25519、Secp256k1、Secp256r1)は、sBPF VMをバイパスして署名をネイティブコードとして検証します。sBPF実行では遅すぎる暗号化操作を処理します。プリコンパイルはCPI経由で呼び出すことはできません。
プリコンパイル済みプログラム
プリコンパイル済みプログラムは、sBPF仮想マシンをバイパスし、validator内でネイティブコードとして実行されます。sBPF実行では遅すぎる暗号化操作を処理します。
ed25519署名の検証
ed25519プログラムは、単一のinstruction内で1つ以上のed25519署名を検証します。
| プログラム | プログラムID | 説明 | Instructions | ソース |
|---|---|---|---|---|
| Ed25519プログラム | Ed25519SigVerify111111111111111111111111111 | ed25519署名を検証します。いずれかの署名が失敗した場合、エラーが返されます。 | Instructions | ソース |
instructionの最初のu8には、チェックする署名の数のカウントが含まれ、その後に1バイトのパディングが続きます。その後、以下の構造体が署名ごとに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 | 説明 | Instructions | ソース |
|---|---|---|---|---|
| Secp256k1プログラム | KeccakSecp256k11111111111111111111111111111 | secp256k1公開鍵リカバリ操作(ecrecover)を検証します。 | Instructions | ソース |
instructionの最初のバイトには、チェックする公開鍵の数のカウントが含まれます。その後、以下の構造体が公開鍵ごとに1回シリアライズされます:
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プログラムは、1つのinstructionあたり最大8つのsecp256r1署名を検証します。
| プログラム | プログラムID | 説明 | Instructions | ソース |
|---|---|---|---|---|
| Secp256r1プログラム | Secp256r1SigVerify1111111111111111111111111 | 最大8つのsecp256r1署名を検証します。署名、公開鍵、メッセージを受け取ります。いずれかが失敗した場合はエラーを返します。 | Instructions | ソース |
instructionの最初のu8は、チェックする署名の数であり、その後に1バイトのパディングが続きます。その後、以下の構造体が署名ごとに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?