22 crate :: Storage ,
33 anchor_lang:: {
44 prelude:: { borsh, AccountInfo , Clock , ProgramError , Pubkey , SolanaSysvar } ,
5- solana_program:: { ed25519_program, pubkey:: PUBKEY_BYTES , sysvar} ,
5+ solana_program:: {
6+ ed25519_program, program_memory:: sol_memcmp, pubkey:: PUBKEY_BYTES , sysvar,
7+ } ,
68 AnchorDeserialize , AnchorSerialize ,
79 } ,
810 bytemuck:: { cast_slice, checked:: try_cast_slice, Pod , Zeroable } ,
@@ -127,6 +129,8 @@ pub enum SignatureVerificationError {
127129 InvalidStorageData ,
128130 #[ error( "not a trusted signer" ) ]
129131 NotTrustedSigner ,
132+ #[ error( "invalid message data" ) ]
133+ InvalidMessageData ,
130134}
131135
132136impl From < SignatureVerificationError > for ProgramError {
@@ -148,6 +152,10 @@ impl From<SignatureVerificationError> for anchor_lang::error::Error {
148152 }
149153}
150154
155+ fn slice_eq ( a : & [ u8 ] , b : & [ u8 ] ) -> bool {
156+ a. len ( ) == b. len ( ) && sol_memcmp ( a, b, a. len ( ) ) == 0
157+ }
158+
151159/// Verifies a ed25519 signature on Solana by checking that the transaction contains
152160/// a correct call to the built-in `ed25519_program`.
153161///
@@ -163,7 +171,6 @@ pub fn verify_message(
163171 message_data : & [ u8 ] ,
164172 ed25519_instruction_index : u16 ,
165173 signature_index : u8 ,
166- message_offset : u16 ,
167174) -> Result < VerifiedMessage , SignatureVerificationError > {
168175 const SOLANA_FORMAT_MAGIC_LE : u32 = 2182742457 ;
169176
@@ -175,25 +182,25 @@ pub fn verify_message(
175182 return Err ( SignatureVerificationError :: Ed25519InstructionMustPrecedeCurrentInstruction ) ;
176183 }
177184
178- let instruction = sysvar:: instructions:: load_instruction_at_checked (
185+ let ed25519_instruction = sysvar:: instructions:: load_instruction_at_checked (
179186 ed25519_instruction_index. into ( ) ,
180187 instructions_sysvar,
181188 )
182189 . map_err ( SignatureVerificationError :: LoadInstructionAtFailed ) ?;
183190
184- if instruction . program_id != ed25519_program:: ID {
191+ if ed25519_instruction . program_id != ed25519_program:: ID {
185192 return Err ( SignatureVerificationError :: InvalidEd25519InstructionProgramId ) ;
186193 }
187- if instruction . data . len ( ) < ED25519_PROGRAM_INPUT_HEADER_LEN {
194+ if ed25519_instruction . data . len ( ) < ED25519_PROGRAM_INPUT_HEADER_LEN {
188195 return Err ( SignatureVerificationError :: InvalidEd25519InstructionDataLength ) ;
189196 }
190197
191- let num_signatures = instruction . data [ 0 ] ;
198+ let num_signatures = ed25519_instruction . data [ 0 ] ;
192199 if signature_index >= num_signatures {
193200 return Err ( SignatureVerificationError :: InvalidSignatureIndex ) ;
194201 }
195202 let args: & [ Ed25519SignatureOffsets ] =
196- try_cast_slice ( & instruction . data [ ED25519_PROGRAM_INPUT_HEADER_LEN ..] )
203+ try_cast_slice ( & ed25519_instruction . data [ ED25519_PROGRAM_INPUT_HEADER_LEN ..] )
197204 . map_err ( |_| SignatureVerificationError :: InvalidEd25519InstructionDataLength ) ?;
198205
199206 let args_len = args
@@ -205,19 +212,37 @@ pub fn verify_message(
205212 }
206213 let offsets = & args[ usize:: from ( signature_index) ] ;
207214
208- let expected_signature_offset = message_offset
209- . checked_add ( MAGIC_LEN )
215+ let message_offset = offsets
216+ . signature_offset
217+ . checked_sub ( MAGIC_LEN )
210218 . ok_or ( SignatureVerificationError :: MessageOffsetOverflow ) ?;
211- if offsets. signature_offset != expected_signature_offset {
212- return Err ( SignatureVerificationError :: InvalidSignatureOffset ) ;
219+
220+ let self_instruction = sysvar:: instructions:: load_instruction_at_checked (
221+ self_instruction_index. into ( ) ,
222+ instructions_sysvar,
223+ )
224+ . map_err ( SignatureVerificationError :: LoadInstructionAtFailed ) ?;
225+
226+ let message_end_offset = offsets
227+ . message_data_offset
228+ . checked_add ( offsets. message_data_size )
229+ . ok_or ( SignatureVerificationError :: MessageOffsetOverflow ) ?;
230+ let expected_message_data = self_instruction
231+ . data
232+ . get ( usize:: from ( message_offset) ..usize:: from ( message_end_offset) )
233+ . ok_or ( SignatureVerificationError :: InvalidMessageOffset ) ?;
234+
235+ if !slice_eq ( expected_message_data, message_data) {
236+ return Err ( SignatureVerificationError :: InvalidMessageData ) ;
213237 }
214238
215239 let magic = LE :: read_u32 ( & message_data[ ..MAGIC_LEN . into ( ) ] ) ;
216240 if magic != SOLANA_FORMAT_MAGIC_LE {
217241 return Err ( SignatureVerificationError :: FormatMagicMismatch ) ;
218242 }
219243
220- let expected_public_key_offset = expected_signature_offset
244+ let expected_public_key_offset = offsets
245+ . signature_offset
221246 . checked_add ( SIGNATURE_LEN )
222247 . ok_or ( SignatureVerificationError :: MessageOffsetOverflow ) ?;
223248 if offsets. public_key_offset != expected_public_key_offset {
0 commit comments