Summary
Precompiles (Ed25519, Secp256k1, Secp256r1) verify signatures as native code, bypassing the sBPF VM. They handle cryptographic operations where sBPF execution would be too slow. Precompiles are not callable via CPI.
Precompiled programs
Precompiled programs bypass the sBPF virtual machine and run as native code within the validator. They handle cryptographic operations where sBPF execution would be too slow.
Verify ed25519 signature
The ed25519 program verifies one or more ed25519 signatures within a single instruction.
| Program | Program ID | Description | Instructions | Source |
|---|---|---|---|---|
| Ed25519 Program | Ed25519SigVerify111111111111111111111111111 | Verifies ed25519 signatures. If any signature fails, an error is returned. | Instructions | Source |
The instruction's first u8 contains a count of the number of signatures to
check, followed by a single byte of padding. After that, the following struct is
serialized once per signature:
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}
Verify secp256k1 recovery
The secp256k1 program verifies secp256k1 public key recovery operations (ecrecover).
| Program | Program ID | Description | Instructions | Source |
|---|---|---|---|---|
| Secp256k1 Program | KeccakSecp256k11111111111111111111111111111 | Verifies secp256k1 public key recovery operations (ecrecover). | Instructions | Source |
The instruction's first byte contains a count of the number of public keys to check. After that, the following struct is serialized once per public key:
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}
Signature and message data can reference any instruction data in the transaction. By specifying the special instructions sysvar, programs can also read data from the transaction itself.
Transaction cost equals the number of signatures to verify multiplied by the per-signature verification cost.
Verify secp256r1 signature
The secp256r1 program verifies up to 8 secp256r1 signatures per instruction.
| Program | Program ID | Description | Instructions | Source |
|---|---|---|---|---|
| Secp256r1 Program | Secp256r1SigVerify1111111111111111111111111 | Verifies up to 8 secp256r1 signatures. Takes a signature, public key, and message. Returns error if any fail. | Instructions | Source |
The instruction's first u8 is a count of signatures to check, followed by a
single byte of padding. After that, the following struct is serialized once per
signature:
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}
Low S values are enforced for all signatures to avoid accidental signature malleability.
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?