Cleanup and standardize precompiles (#19918)
This commit is contained in:
		| @@ -1,27 +1,9 @@ | |||||||
| #![cfg(feature = "full")] | #![cfg(feature = "full")] | ||||||
|  |  | ||||||
| use crate::{decode_error::DecodeError, instruction::Instruction}; | use crate::{feature_set::FeatureSet, instruction::Instruction, precompiles::PrecompileError}; | ||||||
| use bytemuck::{bytes_of, Pod, Zeroable}; | use bytemuck::{bytes_of, Pod, Zeroable}; | ||||||
| use ed25519_dalek::{ed25519::signature::Signature, Signer, Verifier}; | use ed25519_dalek::{ed25519::signature::Signature, Signer, Verifier}; | ||||||
| use thiserror::Error; | use std::sync::Arc; | ||||||
|  |  | ||||||
| #[derive(Error, Debug, Clone, PartialEq)] |  | ||||||
| pub enum Ed25519Error { |  | ||||||
|     #[error("ed25519 public key is not valid")] |  | ||||||
|     InvalidPublicKey, |  | ||||||
|     #[error("ed25519 signature is not valid")] |  | ||||||
|     InvalidSignature, |  | ||||||
|     #[error("offset not valid")] |  | ||||||
|     InvalidDataOffsets, |  | ||||||
|     #[error("instruction is incorrect size")] |  | ||||||
|     InvalidInstructionDataSize, |  | ||||||
| } |  | ||||||
|  |  | ||||||
| impl<T> DecodeError<T> for Ed25519Error { |  | ||||||
|     fn type_of() -> &'static str { |  | ||||||
|         "Ed25519Error" |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| pub const PUBKEY_SERIALIZED_SIZE: usize = 32; | pub const PUBKEY_SERIALIZED_SIZE: usize = 32; | ||||||
| pub const SIGNATURE_SERIALIZED_SIZE: usize = 64; | pub const SIGNATURE_SERIALIZED_SIZE: usize = 64; | ||||||
| @@ -95,19 +77,23 @@ pub fn new_ed25519_instruction(keypair: &ed25519_dalek::Keypair, message: &[u8]) | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| pub fn verify_signatures(data: &[u8], instruction_datas: &[&[u8]]) -> Result<(), Ed25519Error> { | pub fn verify( | ||||||
|  |     data: &[u8], | ||||||
|  |     instruction_datas: &[&[u8]], | ||||||
|  |     _feature_set: &Arc<FeatureSet>, | ||||||
|  | ) -> Result<(), PrecompileError> { | ||||||
|     if data.len() < SIGNATURE_OFFSETS_START { |     if data.len() < SIGNATURE_OFFSETS_START { | ||||||
|         return Err(Ed25519Error::InvalidInstructionDataSize); |         return Err(PrecompileError::InvalidInstructionDataSize); | ||||||
|     } |     } | ||||||
|     let num_signatures = data[0] as usize; |     let num_signatures = data[0] as usize; | ||||||
|     if num_signatures == 0 && data.len() > SIGNATURE_OFFSETS_START { |     if num_signatures == 0 && data.len() > SIGNATURE_OFFSETS_START { | ||||||
|         return Err(Ed25519Error::InvalidInstructionDataSize); |         return Err(PrecompileError::InvalidInstructionDataSize); | ||||||
|     } |     } | ||||||
|     let expected_data_size = num_signatures |     let expected_data_size = num_signatures | ||||||
|         .saturating_mul(SIGNATURE_OFFSETS_SERIALIZED_SIZE) |         .saturating_mul(SIGNATURE_OFFSETS_SERIALIZED_SIZE) | ||||||
|         .saturating_add(SIGNATURE_OFFSETS_START); |         .saturating_add(SIGNATURE_OFFSETS_START); | ||||||
|     if data.len() < expected_data_size { |     if data.len() < expected_data_size { | ||||||
|         return Err(Ed25519Error::InvalidInstructionDataSize); |         return Err(PrecompileError::InvalidInstructionDataSize); | ||||||
|     } |     } | ||||||
|     for i in 0..num_signatures { |     for i in 0..num_signatures { | ||||||
|         let start = i |         let start = i | ||||||
| @@ -117,23 +103,23 @@ pub fn verify_signatures(data: &[u8], instruction_datas: &[&[u8]]) -> Result<(), | |||||||
|  |  | ||||||
|         // bytemuck wants structures aligned |         // bytemuck wants structures aligned | ||||||
|         let offsets: &Ed25519SignatureOffsets = bytemuck::try_from_bytes(&data[start..end]) |         let offsets: &Ed25519SignatureOffsets = bytemuck::try_from_bytes(&data[start..end]) | ||||||
|             .map_err(|_| Ed25519Error::InvalidDataOffsets)?; |             .map_err(|_| PrecompileError::InvalidDataOffsets)?; | ||||||
|  |  | ||||||
|         // Parse out signature |         // Parse out signature | ||||||
|         let signature_index = offsets.signature_instruction_index as usize; |         let signature_index = offsets.signature_instruction_index as usize; | ||||||
|         if signature_index >= instruction_datas.len() { |         if signature_index >= instruction_datas.len() { | ||||||
|             return Err(Ed25519Error::InvalidDataOffsets); |             return Err(PrecompileError::InvalidDataOffsets); | ||||||
|         } |         } | ||||||
|         let signature_instruction = instruction_datas[signature_index]; |         let signature_instruction = instruction_datas[signature_index]; | ||||||
|         let sig_start = offsets.signature_offset as usize; |         let sig_start = offsets.signature_offset as usize; | ||||||
|         let sig_end = sig_start.saturating_add(SIGNATURE_SERIALIZED_SIZE); |         let sig_end = sig_start.saturating_add(SIGNATURE_SERIALIZED_SIZE); | ||||||
|         if sig_end >= signature_instruction.len() { |         if sig_end >= signature_instruction.len() { | ||||||
|             return Err(Ed25519Error::InvalidDataOffsets); |             return Err(PrecompileError::InvalidDataOffsets); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         let signature = |         let signature = | ||||||
|             ed25519_dalek::Signature::from_bytes(&signature_instruction[sig_start..sig_end]) |             ed25519_dalek::Signature::from_bytes(&signature_instruction[sig_start..sig_end]) | ||||||
|                 .map_err(|_| Ed25519Error::InvalidSignature)?; |                 .map_err(|_| PrecompileError::InvalidSignature)?; | ||||||
|  |  | ||||||
|         // Parse out pubkey |         // Parse out pubkey | ||||||
|         let pubkey = get_data_slice( |         let pubkey = get_data_slice( | ||||||
| @@ -144,7 +130,7 @@ pub fn verify_signatures(data: &[u8], instruction_datas: &[&[u8]]) -> Result<(), | |||||||
|         )?; |         )?; | ||||||
|  |  | ||||||
|         let publickey = ed25519_dalek::PublicKey::from_bytes(pubkey) |         let publickey = ed25519_dalek::PublicKey::from_bytes(pubkey) | ||||||
|             .map_err(|_| Ed25519Error::InvalidPublicKey)?; |             .map_err(|_| PrecompileError::InvalidPublicKey)?; | ||||||
|  |  | ||||||
|         // Parse out message |         // Parse out message | ||||||
|         let message = get_data_slice( |         let message = get_data_slice( | ||||||
| @@ -156,7 +142,7 @@ pub fn verify_signatures(data: &[u8], instruction_datas: &[&[u8]]) -> Result<(), | |||||||
|  |  | ||||||
|         publickey |         publickey | ||||||
|             .verify(message, &signature) |             .verify(message, &signature) | ||||||
|             .map_err(|_| Ed25519Error::InvalidSignature)?; |             .map_err(|_| PrecompileError::InvalidSignature)?; | ||||||
|     } |     } | ||||||
|     Ok(()) |     Ok(()) | ||||||
| } | } | ||||||
| @@ -166,16 +152,16 @@ fn get_data_slice<'a>( | |||||||
|     instruction_index: u16, |     instruction_index: u16, | ||||||
|     offset_start: u16, |     offset_start: u16, | ||||||
|     size: usize, |     size: usize, | ||||||
| ) -> Result<&'a [u8], Ed25519Error> { | ) -> Result<&'a [u8], PrecompileError> { | ||||||
|     let signature_index = instruction_index as usize; |     let signature_index = instruction_index as usize; | ||||||
|     if signature_index >= instruction_datas.len() { |     if signature_index >= instruction_datas.len() { | ||||||
|         return Err(Ed25519Error::InvalidDataOffsets); |         return Err(PrecompileError::InvalidDataOffsets); | ||||||
|     } |     } | ||||||
|     let signature_instruction = &instruction_datas[signature_index]; |     let signature_instruction = &instruction_datas[signature_index]; | ||||||
|     let start = offset_start as usize; |     let start = offset_start as usize; | ||||||
|     let end = start.saturating_add(size); |     let end = start.saturating_add(size); | ||||||
|     if end > signature_instruction.len() { |     if end > signature_instruction.len() { | ||||||
|         return Err(Ed25519Error::InvalidDataOffsets); |         return Err(PrecompileError::InvalidDataOffsets); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     Ok(&instruction_datas[signature_index][start..end]) |     Ok(&instruction_datas[signature_index][start..end]) | ||||||
| @@ -188,7 +174,7 @@ pub mod test { | |||||||
|     fn test_case( |     fn test_case( | ||||||
|         num_signatures: u16, |         num_signatures: u16, | ||||||
|         offsets: &Ed25519SignatureOffsets, |         offsets: &Ed25519SignatureOffsets, | ||||||
|     ) -> Result<(), Ed25519Error> { |     ) -> Result<(), PrecompileError> { | ||||||
|         assert_eq!( |         assert_eq!( | ||||||
|             bytemuck::bytes_of(offsets).len(), |             bytemuck::bytes_of(offsets).len(), | ||||||
|             SIGNATURE_OFFSETS_SERIALIZED_SIZE |             SIGNATURE_OFFSETS_SERIALIZED_SIZE | ||||||
| @@ -198,7 +184,11 @@ pub mod test { | |||||||
|         instruction_data[0..SIGNATURE_OFFSETS_START].copy_from_slice(bytes_of(&num_signatures)); |         instruction_data[0..SIGNATURE_OFFSETS_START].copy_from_slice(bytes_of(&num_signatures)); | ||||||
|         instruction_data[SIGNATURE_OFFSETS_START..DATA_START].copy_from_slice(bytes_of(offsets)); |         instruction_data[SIGNATURE_OFFSETS_START..DATA_START].copy_from_slice(bytes_of(offsets)); | ||||||
|  |  | ||||||
|         verify_signatures(&instruction_data, &[&[0u8; 100]]) |         verify( | ||||||
|  |             &instruction_data, | ||||||
|  |             &[&[0u8; 100]], | ||||||
|  |             &Arc::new(FeatureSet::all_enabled()), | ||||||
|  |         ) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     #[test] |     #[test] | ||||||
| @@ -212,8 +202,12 @@ pub mod test { | |||||||
|         instruction_data.truncate(instruction_data.len() - 1); |         instruction_data.truncate(instruction_data.len() - 1); | ||||||
|  |  | ||||||
|         assert_eq!( |         assert_eq!( | ||||||
|             verify_signatures(&instruction_data, &[&[0u8; 100]]), |             verify( | ||||||
|             Err(Ed25519Error::InvalidInstructionDataSize) |                 &instruction_data, | ||||||
|  |                 &[&[0u8; 100]], | ||||||
|  |                 &Arc::new(FeatureSet::all_enabled()), | ||||||
|  |             ), | ||||||
|  |             Err(PrecompileError::InvalidInstructionDataSize) | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
|         let offsets = Ed25519SignatureOffsets { |         let offsets = Ed25519SignatureOffsets { | ||||||
| @@ -222,7 +216,7 @@ pub mod test { | |||||||
|         }; |         }; | ||||||
|         assert_eq!( |         assert_eq!( | ||||||
|             test_case(1, &offsets), |             test_case(1, &offsets), | ||||||
|             Err(Ed25519Error::InvalidDataOffsets) |             Err(PrecompileError::InvalidDataOffsets) | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
|         let offsets = Ed25519SignatureOffsets { |         let offsets = Ed25519SignatureOffsets { | ||||||
| @@ -231,7 +225,7 @@ pub mod test { | |||||||
|         }; |         }; | ||||||
|         assert_eq!( |         assert_eq!( | ||||||
|             test_case(1, &offsets), |             test_case(1, &offsets), | ||||||
|             Err(Ed25519Error::InvalidDataOffsets) |             Err(PrecompileError::InvalidDataOffsets) | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
|         let offsets = Ed25519SignatureOffsets { |         let offsets = Ed25519SignatureOffsets { | ||||||
| @@ -240,7 +234,7 @@ pub mod test { | |||||||
|         }; |         }; | ||||||
|         assert_eq!( |         assert_eq!( | ||||||
|             test_case(1, &offsets), |             test_case(1, &offsets), | ||||||
|             Err(Ed25519Error::InvalidDataOffsets) |             Err(PrecompileError::InvalidDataOffsets) | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -251,7 +245,10 @@ pub mod test { | |||||||
|             message_data_size: 1, |             message_data_size: 1, | ||||||
|             ..Ed25519SignatureOffsets::default() |             ..Ed25519SignatureOffsets::default() | ||||||
|         }; |         }; | ||||||
|         assert_eq!(test_case(1, &offsets), Err(Ed25519Error::InvalidSignature)); |         assert_eq!( | ||||||
|  |             test_case(1, &offsets), | ||||||
|  |             Err(PrecompileError::InvalidSignature) | ||||||
|  |         ); | ||||||
|  |  | ||||||
|         let offsets = Ed25519SignatureOffsets { |         let offsets = Ed25519SignatureOffsets { | ||||||
|             message_data_offset: 100, |             message_data_offset: 100, | ||||||
| @@ -260,7 +257,7 @@ pub mod test { | |||||||
|         }; |         }; | ||||||
|         assert_eq!( |         assert_eq!( | ||||||
|             test_case(1, &offsets), |             test_case(1, &offsets), | ||||||
|             Err(Ed25519Error::InvalidDataOffsets) |             Err(PrecompileError::InvalidDataOffsets) | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
|         let offsets = Ed25519SignatureOffsets { |         let offsets = Ed25519SignatureOffsets { | ||||||
| @@ -270,7 +267,7 @@ pub mod test { | |||||||
|         }; |         }; | ||||||
|         assert_eq!( |         assert_eq!( | ||||||
|             test_case(1, &offsets), |             test_case(1, &offsets), | ||||||
|             Err(Ed25519Error::InvalidDataOffsets) |             Err(PrecompileError::InvalidDataOffsets) | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
|         let offsets = Ed25519SignatureOffsets { |         let offsets = Ed25519SignatureOffsets { | ||||||
| @@ -280,7 +277,7 @@ pub mod test { | |||||||
|         }; |         }; | ||||||
|         assert_eq!( |         assert_eq!( | ||||||
|             test_case(1, &offsets), |             test_case(1, &offsets), | ||||||
|             Err(Ed25519Error::InvalidDataOffsets) |             Err(PrecompileError::InvalidDataOffsets) | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -292,7 +289,7 @@ pub mod test { | |||||||
|         }; |         }; | ||||||
|         assert_eq!( |         assert_eq!( | ||||||
|             test_case(1, &offsets), |             test_case(1, &offsets), | ||||||
|             Err(Ed25519Error::InvalidDataOffsets) |             Err(PrecompileError::InvalidDataOffsets) | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
|         let offsets = Ed25519SignatureOffsets { |         let offsets = Ed25519SignatureOffsets { | ||||||
| @@ -301,7 +298,7 @@ pub mod test { | |||||||
|         }; |         }; | ||||||
|         assert_eq!( |         assert_eq!( | ||||||
|             test_case(1, &offsets), |             test_case(1, &offsets), | ||||||
|             Err(Ed25519Error::InvalidDataOffsets) |             Err(PrecompileError::InvalidDataOffsets) | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -313,7 +310,7 @@ pub mod test { | |||||||
|         }; |         }; | ||||||
|         assert_eq!( |         assert_eq!( | ||||||
|             test_case(1, &offsets), |             test_case(1, &offsets), | ||||||
|             Err(Ed25519Error::InvalidDataOffsets) |             Err(PrecompileError::InvalidDataOffsets) | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
|         let offsets = Ed25519SignatureOffsets { |         let offsets = Ed25519SignatureOffsets { | ||||||
| @@ -322,7 +319,7 @@ pub mod test { | |||||||
|         }; |         }; | ||||||
|         assert_eq!( |         assert_eq!( | ||||||
|             test_case(1, &offsets), |             test_case(1, &offsets), | ||||||
|             Err(Ed25519Error::InvalidDataOffsets) |             Err(PrecompileError::InvalidDataOffsets) | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -36,6 +36,7 @@ pub mod nonce_account; | |||||||
| pub mod nonce_keyed_account; | pub mod nonce_keyed_account; | ||||||
| pub mod packet; | pub mod packet; | ||||||
| pub mod poh_config; | pub mod poh_config; | ||||||
|  | pub mod precompiles; | ||||||
| pub mod process_instruction; | pub mod process_instruction; | ||||||
| pub mod program_utils; | pub mod program_utils; | ||||||
| pub mod pubkey; | pub mod pubkey; | ||||||
|   | |||||||
							
								
								
									
										117
									
								
								sdk/src/precompiles.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								sdk/src/precompiles.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,117 @@ | |||||||
|  | //! @brief Solana precompiled programs | ||||||
|  |  | ||||||
|  | #![cfg(feature = "full")] | ||||||
|  |  | ||||||
|  | use { | ||||||
|  |     crate::{ | ||||||
|  |         decode_error::DecodeError, | ||||||
|  |         feature_set::{ed25519_program_enabled, FeatureSet}, | ||||||
|  |         instruction::CompiledInstruction, | ||||||
|  |         pubkey::Pubkey, | ||||||
|  |     }, | ||||||
|  |     lazy_static::lazy_static, | ||||||
|  |     std::sync::Arc, | ||||||
|  |     thiserror::Error, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /// Precompile errors | ||||||
|  | #[derive(Error, Debug, Clone, PartialEq)] | ||||||
|  | pub enum PrecompileError { | ||||||
|  |     #[error("public key is not valid")] | ||||||
|  |     InvalidPublicKey, | ||||||
|  |     #[error("id is not valid")] | ||||||
|  |     InvalidRecoveryId, | ||||||
|  |     #[error("signature is not valid")] | ||||||
|  |     InvalidSignature, | ||||||
|  |     #[error("offset not valid")] | ||||||
|  |     InvalidDataOffsets, | ||||||
|  |     #[error("instruction is incorrect size")] | ||||||
|  |     InvalidInstructionDataSize, | ||||||
|  | } | ||||||
|  | impl<T> DecodeError<T> for PrecompileError { | ||||||
|  |     fn type_of() -> &'static str { | ||||||
|  |         "PrecompileError" | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /// All precompiled programs must implement the `Verify` function | ||||||
|  | pub type Verify = fn(&[u8], &[&[u8]], &Arc<FeatureSet>) -> std::result::Result<(), PrecompileError>; | ||||||
|  |  | ||||||
|  | /// Information on a precompiled program | ||||||
|  | struct Precompile { | ||||||
|  |     /// Program id | ||||||
|  |     pub program_id: Pubkey, | ||||||
|  |     /// Feature to enable on, `None` indicates always enabled | ||||||
|  |     pub feature: Option<Pubkey>, | ||||||
|  |     /// Verification function | ||||||
|  |     pub verify_fn: Verify, | ||||||
|  | } | ||||||
|  | impl Precompile { | ||||||
|  |     /// Creates a new `Precompile` | ||||||
|  |     pub fn new(program_id: Pubkey, feature: Option<Pubkey>, verify_fn: Verify) -> Self { | ||||||
|  |         Precompile { | ||||||
|  |             program_id, | ||||||
|  |             feature, | ||||||
|  |             verify_fn, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     /// Check if a program id is this precompiled program | ||||||
|  |     pub fn check_id(&self, program_id: &Pubkey, feature_set: &Arc<FeatureSet>) -> bool { | ||||||
|  |         self.feature.map_or(true, |f| feature_set.is_active(&f)) && self.program_id == *program_id | ||||||
|  |     } | ||||||
|  |     /// Verify this precompiled program | ||||||
|  |     pub fn verify( | ||||||
|  |         &self, | ||||||
|  |         data: &[u8], | ||||||
|  |         instruction_datas: &[&[u8]], | ||||||
|  |         feature_set: &Arc<FeatureSet>, | ||||||
|  |     ) -> std::result::Result<(), PrecompileError> { | ||||||
|  |         (self.verify_fn)(data, instruction_datas, feature_set) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | lazy_static! { | ||||||
|  |     /// The list of all precompiled programs | ||||||
|  |     static ref PRECOMPILES: Vec<Precompile> = vec![ | ||||||
|  |         Precompile::new( | ||||||
|  |             crate::secp256k1_program::id(), | ||||||
|  |             None, | ||||||
|  |             crate::secp256k1_instruction::verify, | ||||||
|  |         ), | ||||||
|  |         Precompile::new( | ||||||
|  |             crate::ed25519_program::id(), | ||||||
|  |             Some(ed25519_program_enabled::id()), | ||||||
|  |             crate::ed25519_instruction::verify, | ||||||
|  |         ), | ||||||
|  |     ]; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /// Check if a program is a precompiled program | ||||||
|  | pub fn is_precompile(program_id: &Pubkey, feature_set: &Arc<FeatureSet>) -> bool { | ||||||
|  |     PRECOMPILES | ||||||
|  |         .iter() | ||||||
|  |         .any(|precompile| precompile.check_id(program_id, feature_set)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /// Check that a program is precompiled and if so verify it | ||||||
|  | pub fn verify_if_precompile( | ||||||
|  |     program_id: &Pubkey, | ||||||
|  |     precompile_instruction: &CompiledInstruction, | ||||||
|  |     all_instructions: &[CompiledInstruction], | ||||||
|  |     feature_set: &Arc<FeatureSet>, | ||||||
|  | ) -> Result<(), PrecompileError> { | ||||||
|  |     for precompile in PRECOMPILES.iter() { | ||||||
|  |         if precompile.check_id(program_id, feature_set) { | ||||||
|  |             let instruction_datas: Vec<_> = all_instructions | ||||||
|  |                 .iter() | ||||||
|  |                 .map(|instruction| instruction.data.as_ref()) | ||||||
|  |                 .collect(); | ||||||
|  |             return precompile.verify( | ||||||
|  |                 &precompile_instruction.data, | ||||||
|  |                 &instruction_datas, | ||||||
|  |                 feature_set, | ||||||
|  |             ); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     Ok(()) | ||||||
|  | } | ||||||
| @@ -1,16 +1,13 @@ | |||||||
| #![cfg(feature = "full")] | #![cfg(feature = "full")] | ||||||
|  |  | ||||||
| use crate::instruction::Instruction; | use crate::{ | ||||||
|  |     feature_set::{libsecp256k1_0_5_upgrade_enabled, libsecp256k1_fail_on_bad_count, FeatureSet}, | ||||||
|  |     instruction::Instruction, | ||||||
|  |     precompiles::PrecompileError, | ||||||
|  | }; | ||||||
| use digest::Digest; | use digest::Digest; | ||||||
| use serde_derive::{Deserialize, Serialize}; | use serde_derive::{Deserialize, Serialize}; | ||||||
|  | use std::sync::Arc; | ||||||
| #[derive(Debug, PartialEq)] |  | ||||||
| pub enum Secp256k1Error { |  | ||||||
|     InvalidSignature, |  | ||||||
|     InvalidRecoveryId, |  | ||||||
|     InvalidDataOffsets, |  | ||||||
|     InvalidInstructionDataSize, |  | ||||||
| } |  | ||||||
|  |  | ||||||
| pub const HASHED_PUBKEY_SERIALIZED_SIZE: usize = 20; | pub const HASHED_PUBKEY_SERIALIZED_SIZE: usize = 20; | ||||||
| pub const SIGNATURE_SERIALIZED_SIZE: usize = 64; | pub const SIGNATURE_SERIALIZED_SIZE: usize = 64; | ||||||
| @@ -99,27 +96,27 @@ pub fn construct_eth_pubkey( | |||||||
|     addr |     addr | ||||||
| } | } | ||||||
|  |  | ||||||
| pub fn verify_eth_addresses( | pub fn verify( | ||||||
|     data: &[u8], |     data: &[u8], | ||||||
|     instruction_datas: &[&[u8]], |     instruction_datas: &[&[u8]], | ||||||
|     libsecp256k1_0_5_upgrade_enabled: bool, |     feature_set: &Arc<FeatureSet>, | ||||||
|     libsecp256k1_fail_on_bad_count: bool, | ) -> Result<(), PrecompileError> { | ||||||
| ) -> Result<(), Secp256k1Error> { |  | ||||||
|     if data.is_empty() { |     if data.is_empty() { | ||||||
|         return Err(Secp256k1Error::InvalidInstructionDataSize); |         return Err(PrecompileError::InvalidInstructionDataSize); | ||||||
|     } |     } | ||||||
|     let count = data[0] as usize; |     let count = data[0] as usize; | ||||||
|     if libsecp256k1_fail_on_bad_count && count == 0 && data.len() > 1 { |     if feature_set.is_active(&libsecp256k1_fail_on_bad_count::id()) && count == 0 && data.len() > 1 | ||||||
|  |     { | ||||||
|         // count is zero but the instruction data indicates that is probably not |         // count is zero but the instruction data indicates that is probably not | ||||||
|         // correct, fail the instruction to catch probable invalid secp256k1 |         // correct, fail the instruction to catch probable invalid secp256k1 | ||||||
|         // instruction construction. |         // instruction construction. | ||||||
|         return Err(Secp256k1Error::InvalidInstructionDataSize); |         return Err(PrecompileError::InvalidInstructionDataSize); | ||||||
|     } |     } | ||||||
|     let expected_data_size = count |     let expected_data_size = count | ||||||
|         .saturating_mul(SIGNATURE_OFFSETS_SERIALIZED_SIZE) |         .saturating_mul(SIGNATURE_OFFSETS_SERIALIZED_SIZE) | ||||||
|         .saturating_add(1); |         .saturating_add(1); | ||||||
|     if data.len() < expected_data_size { |     if data.len() < expected_data_size { | ||||||
|         return Err(Secp256k1Error::InvalidInstructionDataSize); |         return Err(PrecompileError::InvalidInstructionDataSize); | ||||||
|     } |     } | ||||||
|     for i in 0..count { |     for i in 0..count { | ||||||
|         let start = i |         let start = i | ||||||
| @@ -128,21 +125,21 @@ pub fn verify_eth_addresses( | |||||||
|         let end = start.saturating_add(SIGNATURE_OFFSETS_SERIALIZED_SIZE); |         let end = start.saturating_add(SIGNATURE_OFFSETS_SERIALIZED_SIZE); | ||||||
|  |  | ||||||
|         let offsets: SecpSignatureOffsets = bincode::deserialize(&data[start..end]) |         let offsets: SecpSignatureOffsets = bincode::deserialize(&data[start..end]) | ||||||
|             .map_err(|_| Secp256k1Error::InvalidSignature)?; |             .map_err(|_| PrecompileError::InvalidSignature)?; | ||||||
|  |  | ||||||
|         // Parse out signature |         // Parse out signature | ||||||
|         let signature_index = offsets.signature_instruction_index as usize; |         let signature_index = offsets.signature_instruction_index as usize; | ||||||
|         if signature_index >= instruction_datas.len() { |         if signature_index >= instruction_datas.len() { | ||||||
|             return Err(Secp256k1Error::InvalidInstructionDataSize); |             return Err(PrecompileError::InvalidInstructionDataSize); | ||||||
|         } |         } | ||||||
|         let signature_instruction = instruction_datas[signature_index]; |         let signature_instruction = instruction_datas[signature_index]; | ||||||
|         let sig_start = offsets.signature_offset as usize; |         let sig_start = offsets.signature_offset as usize; | ||||||
|         let sig_end = sig_start.saturating_add(SIGNATURE_SERIALIZED_SIZE); |         let sig_end = sig_start.saturating_add(SIGNATURE_SERIALIZED_SIZE); | ||||||
|         if sig_end >= signature_instruction.len() { |         if sig_end >= signature_instruction.len() { | ||||||
|             return Err(Secp256k1Error::InvalidSignature); |             return Err(PrecompileError::InvalidSignature); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         let sig_parse_result = if libsecp256k1_0_5_upgrade_enabled { |         let sig_parse_result = if feature_set.is_active(&libsecp256k1_0_5_upgrade_enabled::id()) { | ||||||
|             libsecp256k1::Signature::parse_standard_slice( |             libsecp256k1::Signature::parse_standard_slice( | ||||||
|                 &signature_instruction[sig_start..sig_end], |                 &signature_instruction[sig_start..sig_end], | ||||||
|             ) |             ) | ||||||
| @@ -152,10 +149,10 @@ pub fn verify_eth_addresses( | |||||||
|             ) |             ) | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
|         let signature = sig_parse_result.map_err(|_| Secp256k1Error::InvalidSignature)?; |         let signature = sig_parse_result.map_err(|_| PrecompileError::InvalidSignature)?; | ||||||
|  |  | ||||||
|         let recovery_id = libsecp256k1::RecoveryId::parse(signature_instruction[sig_end]) |         let recovery_id = libsecp256k1::RecoveryId::parse(signature_instruction[sig_end]) | ||||||
|             .map_err(|_| Secp256k1Error::InvalidRecoveryId)?; |             .map_err(|_| PrecompileError::InvalidRecoveryId)?; | ||||||
|  |  | ||||||
|         // Parse out pubkey |         // Parse out pubkey | ||||||
|         let eth_address_slice = get_data_slice( |         let eth_address_slice = get_data_slice( | ||||||
| @@ -182,11 +179,11 @@ pub fn verify_eth_addresses( | |||||||
|             &signature, |             &signature, | ||||||
|             &recovery_id, |             &recovery_id, | ||||||
|         ) |         ) | ||||||
|         .map_err(|_| Secp256k1Error::InvalidSignature)?; |         .map_err(|_| PrecompileError::InvalidSignature)?; | ||||||
|         let eth_address = construct_eth_pubkey(&pubkey); |         let eth_address = construct_eth_pubkey(&pubkey); | ||||||
|  |  | ||||||
|         if eth_address_slice != eth_address { |         if eth_address_slice != eth_address { | ||||||
|             return Err(Secp256k1Error::InvalidSignature); |             return Err(PrecompileError::InvalidSignature); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     Ok(()) |     Ok(()) | ||||||
| @@ -197,16 +194,16 @@ fn get_data_slice<'a>( | |||||||
|     instruction_index: u8, |     instruction_index: u8, | ||||||
|     offset_start: u16, |     offset_start: u16, | ||||||
|     size: usize, |     size: usize, | ||||||
| ) -> Result<&'a [u8], Secp256k1Error> { | ) -> Result<&'a [u8], PrecompileError> { | ||||||
|     let signature_index = instruction_index as usize; |     let signature_index = instruction_index as usize; | ||||||
|     if signature_index >= instruction_datas.len() { |     if signature_index >= instruction_datas.len() { | ||||||
|         return Err(Secp256k1Error::InvalidDataOffsets); |         return Err(PrecompileError::InvalidDataOffsets); | ||||||
|     } |     } | ||||||
|     let signature_instruction = &instruction_datas[signature_index]; |     let signature_instruction = &instruction_datas[signature_index]; | ||||||
|     let start = offset_start as usize; |     let start = offset_start as usize; | ||||||
|     let end = start.saturating_add(size); |     let end = start.saturating_add(size); | ||||||
|     if end > signature_instruction.len() { |     if end > signature_instruction.len() { | ||||||
|         return Err(Secp256k1Error::InvalidSignature); |         return Err(PrecompileError::InvalidSignature); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     Ok(&instruction_datas[signature_index][start..end]) |     Ok(&instruction_datas[signature_index][start..end]) | ||||||
| @@ -216,13 +213,23 @@ fn get_data_slice<'a>( | |||||||
| pub mod test { | pub mod test { | ||||||
|     use super::*; |     use super::*; | ||||||
|  |  | ||||||
|     fn test_case(num_signatures: u8, offsets: &SecpSignatureOffsets) -> Result<(), Secp256k1Error> { |     fn test_case( | ||||||
|  |         num_signatures: u8, | ||||||
|  |         offsets: &SecpSignatureOffsets, | ||||||
|  |     ) -> Result<(), PrecompileError> { | ||||||
|         let mut instruction_data = vec![0u8; DATA_START]; |         let mut instruction_data = vec![0u8; DATA_START]; | ||||||
|         instruction_data[0] = num_signatures; |         instruction_data[0] = num_signatures; | ||||||
|         let writer = std::io::Cursor::new(&mut instruction_data[1..]); |         let writer = std::io::Cursor::new(&mut instruction_data[1..]); | ||||||
|         bincode::serialize_into(writer, &offsets).unwrap(); |         bincode::serialize_into(writer, &offsets).unwrap(); | ||||||
|  |         let mut feature_set = FeatureSet::all_enabled(); | ||||||
|  |         feature_set | ||||||
|  |             .active | ||||||
|  |             .remove(&libsecp256k1_0_5_upgrade_enabled::id()); | ||||||
|  |         feature_set | ||||||
|  |             .inactive | ||||||
|  |             .insert(libsecp256k1_0_5_upgrade_enabled::id()); | ||||||
|  |  | ||||||
|         verify_eth_addresses(&instruction_data, &[&[0u8; 100]], false, true) |         verify(&instruction_data, &[&[0u8; 100]], &Arc::new(feature_set)) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     #[test] |     #[test] | ||||||
| @@ -235,10 +242,17 @@ pub mod test { | |||||||
|         let writer = std::io::Cursor::new(&mut instruction_data[1..]); |         let writer = std::io::Cursor::new(&mut instruction_data[1..]); | ||||||
|         bincode::serialize_into(writer, &offsets).unwrap(); |         bincode::serialize_into(writer, &offsets).unwrap(); | ||||||
|         instruction_data.truncate(instruction_data.len() - 1); |         instruction_data.truncate(instruction_data.len() - 1); | ||||||
|  |         let mut feature_set = FeatureSet::all_enabled(); | ||||||
|  |         feature_set | ||||||
|  |             .active | ||||||
|  |             .remove(&libsecp256k1_0_5_upgrade_enabled::id()); | ||||||
|  |         feature_set | ||||||
|  |             .inactive | ||||||
|  |             .insert(libsecp256k1_0_5_upgrade_enabled::id()); | ||||||
|  |  | ||||||
|         assert_eq!( |         assert_eq!( | ||||||
|             verify_eth_addresses(&instruction_data, &[&[0u8; 100]], false, true), |             verify(&instruction_data, &[&[0u8; 100]], &Arc::new(feature_set)), | ||||||
|             Err(Secp256k1Error::InvalidInstructionDataSize) |             Err(PrecompileError::InvalidInstructionDataSize) | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
|         let offsets = SecpSignatureOffsets { |         let offsets = SecpSignatureOffsets { | ||||||
| @@ -247,7 +261,7 @@ pub mod test { | |||||||
|         }; |         }; | ||||||
|         assert_eq!( |         assert_eq!( | ||||||
|             test_case(1, &offsets), |             test_case(1, &offsets), | ||||||
|             Err(Secp256k1Error::InvalidInstructionDataSize) |             Err(PrecompileError::InvalidInstructionDataSize) | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
|         let offsets = SecpSignatureOffsets { |         let offsets = SecpSignatureOffsets { | ||||||
| @@ -256,7 +270,7 @@ pub mod test { | |||||||
|         }; |         }; | ||||||
|         assert_eq!( |         assert_eq!( | ||||||
|             test_case(1, &offsets), |             test_case(1, &offsets), | ||||||
|             Err(Secp256k1Error::InvalidDataOffsets) |             Err(PrecompileError::InvalidDataOffsets) | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
|         let offsets = SecpSignatureOffsets { |         let offsets = SecpSignatureOffsets { | ||||||
| @@ -265,7 +279,7 @@ pub mod test { | |||||||
|         }; |         }; | ||||||
|         assert_eq!( |         assert_eq!( | ||||||
|             test_case(1, &offsets), |             test_case(1, &offsets), | ||||||
|             Err(Secp256k1Error::InvalidDataOffsets) |             Err(PrecompileError::InvalidDataOffsets) | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -278,7 +292,7 @@ pub mod test { | |||||||
|         }; |         }; | ||||||
|         assert_eq!( |         assert_eq!( | ||||||
|             test_case(1, &offsets), |             test_case(1, &offsets), | ||||||
|             Err(Secp256k1Error::InvalidSignature) |             Err(PrecompileError::InvalidSignature) | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
|         let offsets = SecpSignatureOffsets { |         let offsets = SecpSignatureOffsets { | ||||||
| @@ -288,7 +302,7 @@ pub mod test { | |||||||
|         }; |         }; | ||||||
|         assert_eq!( |         assert_eq!( | ||||||
|             test_case(1, &offsets), |             test_case(1, &offsets), | ||||||
|             Err(Secp256k1Error::InvalidSignature) |             Err(PrecompileError::InvalidSignature) | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
|         let offsets = SecpSignatureOffsets { |         let offsets = SecpSignatureOffsets { | ||||||
| @@ -298,7 +312,7 @@ pub mod test { | |||||||
|         }; |         }; | ||||||
|         assert_eq!( |         assert_eq!( | ||||||
|             test_case(1, &offsets), |             test_case(1, &offsets), | ||||||
|             Err(Secp256k1Error::InvalidSignature) |             Err(PrecompileError::InvalidSignature) | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
|         let offsets = SecpSignatureOffsets { |         let offsets = SecpSignatureOffsets { | ||||||
| @@ -308,7 +322,7 @@ pub mod test { | |||||||
|         }; |         }; | ||||||
|         assert_eq!( |         assert_eq!( | ||||||
|             test_case(1, &offsets), |             test_case(1, &offsets), | ||||||
|             Err(Secp256k1Error::InvalidSignature) |             Err(PrecompileError::InvalidSignature) | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -320,7 +334,7 @@ pub mod test { | |||||||
|         }; |         }; | ||||||
|         assert_eq!( |         assert_eq!( | ||||||
|             test_case(1, &offsets), |             test_case(1, &offsets), | ||||||
|             Err(Secp256k1Error::InvalidSignature) |             Err(PrecompileError::InvalidSignature) | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
|         let offsets = SecpSignatureOffsets { |         let offsets = SecpSignatureOffsets { | ||||||
| @@ -329,7 +343,7 @@ pub mod test { | |||||||
|         }; |         }; | ||||||
|         assert_eq!( |         assert_eq!( | ||||||
|             test_case(1, &offsets), |             test_case(1, &offsets), | ||||||
|             Err(Secp256k1Error::InvalidSignature) |             Err(PrecompileError::InvalidSignature) | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -341,7 +355,7 @@ pub mod test { | |||||||
|         }; |         }; | ||||||
|         assert_eq!( |         assert_eq!( | ||||||
|             test_case(1, &offsets), |             test_case(1, &offsets), | ||||||
|             Err(Secp256k1Error::InvalidSignature) |             Err(PrecompileError::InvalidSignature) | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
|         let offsets = SecpSignatureOffsets { |         let offsets = SecpSignatureOffsets { | ||||||
| @@ -350,7 +364,7 @@ pub mod test { | |||||||
|         }; |         }; | ||||||
|         assert_eq!( |         assert_eq!( | ||||||
|             test_case(1, &offsets), |             test_case(1, &offsets), | ||||||
|             Err(Secp256k1Error::InvalidSignature) |             Err(PrecompileError::InvalidSignature) | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -363,9 +377,17 @@ pub mod test { | |||||||
|         instruction_data[0] = 0; |         instruction_data[0] = 0; | ||||||
|         let writer = std::io::Cursor::new(&mut instruction_data[1..]); |         let writer = std::io::Cursor::new(&mut instruction_data[1..]); | ||||||
|         bincode::serialize_into(writer, &offsets).unwrap(); |         bincode::serialize_into(writer, &offsets).unwrap(); | ||||||
|  |         let mut feature_set = FeatureSet::all_enabled(); | ||||||
|  |         feature_set | ||||||
|  |             .active | ||||||
|  |             .remove(&libsecp256k1_0_5_upgrade_enabled::id()); | ||||||
|  |         feature_set | ||||||
|  |             .inactive | ||||||
|  |             .insert(libsecp256k1_0_5_upgrade_enabled::id()); | ||||||
|  |  | ||||||
|         assert_eq!( |         assert_eq!( | ||||||
|             verify_eth_addresses(&instruction_data, &[&[0u8; 100]], false, true), |             verify(&instruction_data, &[&[0u8; 100]], &Arc::new(feature_set)), | ||||||
|             Err(Secp256k1Error::InvalidInstructionDataSize) |             Err(PrecompileError::InvalidInstructionDataSize) | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -4,15 +4,14 @@ | |||||||
|  |  | ||||||
| use { | use { | ||||||
|     crate::{ |     crate::{ | ||||||
|         ed25519_instruction::verify_signatures, |  | ||||||
|         hash::Hash, |         hash::Hash, | ||||||
|         instruction::{CompiledInstruction, Instruction, InstructionError}, |         instruction::{CompiledInstruction, Instruction, InstructionError}, | ||||||
|         message::{Message, SanitizeMessageError}, |         message::{Message, SanitizeMessageError}, | ||||||
|         nonce::NONCED_TX_MARKER_IX_INDEX, |         nonce::NONCED_TX_MARKER_IX_INDEX, | ||||||
|  |         precompiles::verify_if_precompile, | ||||||
|         program_utils::limited_deserialize, |         program_utils::limited_deserialize, | ||||||
|         pubkey::Pubkey, |         pubkey::Pubkey, | ||||||
|         sanitize::{Sanitize, SanitizeError}, |         sanitize::{Sanitize, SanitizeError}, | ||||||
|         secp256k1_instruction::verify_eth_addresses, |  | ||||||
|         short_vec, |         short_vec, | ||||||
|         signature::{Signature, SignerError}, |         signature::{Signature, SignerError}, | ||||||
|         signers::Signers, |         signers::Signers, | ||||||
| @@ -433,6 +432,7 @@ impl Transaction { | |||||||
|             .collect() |             .collect() | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /// Verify the precompiled programs in this transaction | ||||||
|     pub fn verify_precompiles(&self, feature_set: &Arc<feature_set::FeatureSet>) -> Result<()> { |     pub fn verify_precompiles(&self, feature_set: &Arc<feature_set::FeatureSet>) -> Result<()> { | ||||||
|         for instruction in &self.message().instructions { |         for instruction in &self.message().instructions { | ||||||
|             // The Transaction may not be sanitized at this point |             // The Transaction may not be sanitized at this point | ||||||
| @@ -440,34 +440,14 @@ impl Transaction { | |||||||
|                 return Err(TransactionError::AccountNotFound); |                 return Err(TransactionError::AccountNotFound); | ||||||
|             } |             } | ||||||
|             let program_id = &self.message().account_keys[instruction.program_id_index as usize]; |             let program_id = &self.message().account_keys[instruction.program_id_index as usize]; | ||||||
|             if crate::secp256k1_program::check_id(program_id) { |  | ||||||
|                 let instruction_datas: Vec<_> = self |             verify_if_precompile( | ||||||
|                     .message() |                 program_id, | ||||||
|                     .instructions |                 instruction, | ||||||
|                     .iter() |                 &self.message().instructions, | ||||||
|                     .map(|instruction| instruction.data.as_ref()) |                 feature_set, | ||||||
|                     .collect(); |             ) | ||||||
|                 let data = &instruction.data; |             .map_err(|_| TransactionError::InvalidAccountIndex)?; | ||||||
|                 let e = verify_eth_addresses( |  | ||||||
|                     data, |  | ||||||
|                     &instruction_datas, |  | ||||||
|                     feature_set.is_active(&feature_set::libsecp256k1_0_5_upgrade_enabled::id()), |  | ||||||
|                     feature_set.is_active(&feature_set::libsecp256k1_fail_on_bad_count::id()), |  | ||||||
|                 ); |  | ||||||
|                 e.map_err(|_| TransactionError::InvalidAccountIndex)?; |  | ||||||
|             } else if crate::ed25519_program::check_id(program_id) |  | ||||||
|                 && feature_set.is_active(&feature_set::ed25519_program_enabled::id()) |  | ||||||
|             { |  | ||||||
|                 let instruction_datas: Vec<_> = self |  | ||||||
|                     .message() |  | ||||||
|                     .instructions |  | ||||||
|                     .iter() |  | ||||||
|                     .map(|instruction| instruction.data.as_ref()) |  | ||||||
|                     .collect(); |  | ||||||
|                 let data = &instruction.data; |  | ||||||
|                 let e = verify_signatures(data, &instruction_datas); |  | ||||||
|                 e.map_err(|_| TransactionError::InvalidAccountIndex)?; |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|         Ok(()) |         Ok(()) | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -2,15 +2,13 @@ | |||||||
|  |  | ||||||
| use { | use { | ||||||
|     crate::{ |     crate::{ | ||||||
|         ed25519_instruction::verify_signatures, |  | ||||||
|         hash::Hash, |         hash::Hash, | ||||||
|         message::{v0, MappedAddresses, MappedMessage, SanitizedMessage, VersionedMessage}, |         message::{v0, MappedAddresses, MappedMessage, SanitizedMessage, VersionedMessage}, | ||||||
|         nonce::NONCED_TX_MARKER_IX_INDEX, |         nonce::NONCED_TX_MARKER_IX_INDEX, | ||||||
|  |         precompiles::verify_if_precompile, | ||||||
|         program_utils::limited_deserialize, |         program_utils::limited_deserialize, | ||||||
|         pubkey::Pubkey, |         pubkey::Pubkey, | ||||||
|         sanitize::Sanitize, |         sanitize::Sanitize, | ||||||
|         secp256k1_instruction::verify_eth_addresses, |  | ||||||
|         secp256k1_program, |  | ||||||
|         signature::Signature, |         signature::Signature, | ||||||
|         solana_sdk::feature_set, |         solana_sdk::feature_set, | ||||||
|         transaction::{Result, Transaction, TransactionError, VersionedTransaction}, |         transaction::{Result, Transaction, TransactionError, VersionedTransaction}, | ||||||
| @@ -205,37 +203,16 @@ impl SanitizedTransaction { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// Verify the encoded secp256k1 signatures in this transaction |     /// Verify the precompiled programs in this transaction | ||||||
|     pub fn verify_precompiles(&self, feature_set: &Arc<feature_set::FeatureSet>) -> Result<()> { |     pub fn verify_precompiles(&self, feature_set: &Arc<feature_set::FeatureSet>) -> Result<()> { | ||||||
|         for (program_id, instruction) in self.message.program_instructions_iter() { |         for (program_id, instruction) in self.message.program_instructions_iter() { | ||||||
|             if secp256k1_program::check_id(program_id) { |             verify_if_precompile( | ||||||
|                 let instruction_datas: Vec<_> = self |                 program_id, | ||||||
|                     .message |                 instruction, | ||||||
|                     .instructions() |                 self.message().instructions(), | ||||||
|                     .iter() |                 feature_set, | ||||||
|                     .map(|instruction| instruction.data.as_ref()) |             ) | ||||||
|                     .collect(); |             .map_err(|_| TransactionError::InvalidAccountIndex)?; | ||||||
|                 let data = &instruction.data; |  | ||||||
|                 let e = verify_eth_addresses( |  | ||||||
|                     data, |  | ||||||
|                     &instruction_datas, |  | ||||||
|                     feature_set.is_active(&feature_set::libsecp256k1_0_5_upgrade_enabled::id()), |  | ||||||
|                     feature_set.is_active(&feature_set::libsecp256k1_fail_on_bad_count::id()), |  | ||||||
|                 ); |  | ||||||
|                 e.map_err(|_| TransactionError::InvalidAccountIndex)?; |  | ||||||
|             } else if crate::ed25519_program::check_id(program_id) |  | ||||||
|                 && feature_set.is_active(&feature_set::ed25519_program_enabled::id()) |  | ||||||
|             { |  | ||||||
|                 let instruction_datas: Vec<_> = self |  | ||||||
|                     .message() |  | ||||||
|                     .instructions() |  | ||||||
|                     .iter() |  | ||||||
|                     .map(|instruction| instruction.data.as_ref()) |  | ||||||
|                     .collect(); |  | ||||||
|                 let data = &instruction.data; |  | ||||||
|                 let e = verify_signatures(data, &instruction_datas); |  | ||||||
|                 e.map_err(|_| TransactionError::InvalidAccountIndex)?; |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|         Ok(()) |         Ok(()) | ||||||
|     } |     } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user