use std::convert::TryInto;
use anyhow::Result;
pub const HASHED_PUBKEY_SERIALIZED_SIZE: usize = 20;
pub const SIGNATURE_SERIALIZED_SIZE: usize = 64;
pub const SIGNATURE_OFFSETS_SERIALIZED_SIZE: usize = 11;
#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct SecpSignatureOffsets {
pub signature_offset: u16,
pub signature_instruction_index: u8,
pub eth_address_offset: u16,
pub eth_address_instruction_index: u8,
pub message_data_offset: u16,
pub message_data_size: u16,
pub message_instruction_index: u8,
}
#[derive(Debug)]
pub struct ParsedSignatureData {
pub offsets: SecpSignatureOffsets,
pub eth_address: [u8; HASHED_PUBKEY_SERIALIZED_SIZE],
pub signature: [u8; SIGNATURE_SERIALIZED_SIZE],
pub recovery_id: u8,
pub message: Vec<u8>,
}
pub struct SecpSysvar;
impl SecpSysvar {
pub fn parse_combined_secp256k1_instruction(data: &[u8]) -> Result<Vec<ParsedSignatureData>> {
let mut parsed_signatures = Vec::new();
let num_signatures = data[0] as usize;
let mut offset = 1;
for _ in 0..num_signatures {
let signature_offset = u16::from_le_bytes([data[offset], data[offset + 1]]);
let signature_instruction_index = data[offset + 2];
let eth_address_offset = u16::from_le_bytes([data[offset + 3], data[offset + 4]]);
let eth_address_instruction_index = data[offset + 5];
let message_data_offset = u16::from_le_bytes([data[offset + 6], data[offset + 7]]);
let message_data_size = u16::from_le_bytes([data[offset + 8], data[offset + 9]]);
let message_instruction_index = data[offset + 10];
let offsets = SecpSignatureOffsets {
signature_offset,
signature_instruction_index,
eth_address_offset,
eth_address_instruction_index,
message_data_offset,
message_data_size,
message_instruction_index,
};
let eth_address = data[eth_address_offset as usize
..eth_address_offset as usize + HASHED_PUBKEY_SERIALIZED_SIZE]
.try_into()
.unwrap();
let signature = data
[signature_offset as usize..signature_offset as usize + SIGNATURE_SERIALIZED_SIZE]
.try_into()
.unwrap();
let recovery_id = data[signature_offset as usize + SIGNATURE_SERIALIZED_SIZE];
let message = data[message_data_offset as usize
..message_data_offset as usize + message_data_size as usize]
.to_vec();
parsed_signatures.push(ParsedSignatureData {
offsets,
eth_address,
signature,
recovery_id,
message,
});
offset += SIGNATURE_OFFSETS_SERIALIZED_SIZE;
}
Ok(parsed_signatures)
}
}