|
|
@@ -347,23 +347,75 @@ impl SanitizedMessage {
|
|
|
}
|
|
|
|
|
|
pub fn num_signatures(&self) -> u64 {
|
|
|
- let mut num_signatures = u64::from(self.header().num_required_signatures);
|
|
|
- // This next part is really calculating the number of pre-processor
|
|
|
- // operations being done and treating them like a signature
|
|
|
+ self.get_signature_details().total_signatures()
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn num_write_locks(&self) -> u64 {
|
|
|
+ self.account_keys()
|
|
|
+ .len()
|
|
|
+ .saturating_sub(self.num_readonly_accounts()) as u64
|
|
|
+ }
|
|
|
+
|
|
|
+ /// return detailed signature counts
|
|
|
+ pub fn get_signature_details(&self) -> TransactionSignatureDetails {
|
|
|
+ let mut transaction_signature_details = TransactionSignatureDetails {
|
|
|
+ num_transaction_signatures: u64::from(self.header().num_required_signatures),
|
|
|
+ ..TransactionSignatureDetails::default()
|
|
|
+ };
|
|
|
+
|
|
|
+ // counting the number of pre-processor operations separately
|
|
|
for (program_id, instruction) in self.program_instructions_iter() {
|
|
|
- if secp256k1_program::check_id(program_id) || ed25519_program::check_id(program_id) {
|
|
|
+ if secp256k1_program::check_id(program_id) {
|
|
|
if let Some(num_verifies) = instruction.data.first() {
|
|
|
- num_signatures = num_signatures.saturating_add(u64::from(*num_verifies));
|
|
|
+ transaction_signature_details.num_secp256k1_instruction_signatures =
|
|
|
+ transaction_signature_details
|
|
|
+ .num_secp256k1_instruction_signatures
|
|
|
+ .saturating_add(u64::from(*num_verifies));
|
|
|
+ }
|
|
|
+ } else if ed25519_program::check_id(program_id) {
|
|
|
+ if let Some(num_verifies) = instruction.data.first() {
|
|
|
+ transaction_signature_details.num_ed25519_instruction_signatures =
|
|
|
+ transaction_signature_details
|
|
|
+ .num_ed25519_instruction_signatures
|
|
|
+ .saturating_add(u64::from(*num_verifies));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- num_signatures
|
|
|
+
|
|
|
+ transaction_signature_details
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- pub fn num_write_locks(&self) -> u64 {
|
|
|
- self.account_keys()
|
|
|
- .len()
|
|
|
- .saturating_sub(self.num_readonly_accounts()) as u64
|
|
|
+#[derive(Default)]
|
|
|
+/// Transaction signature details including the number of transaction signatures
|
|
|
+/// and precompile signatures.
|
|
|
+pub struct TransactionSignatureDetails {
|
|
|
+ num_transaction_signatures: u64,
|
|
|
+ num_secp256k1_instruction_signatures: u64,
|
|
|
+ num_ed25519_instruction_signatures: u64,
|
|
|
+}
|
|
|
+
|
|
|
+impl TransactionSignatureDetails {
|
|
|
+ /// return total number of signature, treating pre-processor operations as signature
|
|
|
+ pub(crate) fn total_signatures(&self) -> u64 {
|
|
|
+ self.num_transaction_signatures
|
|
|
+ .saturating_add(self.num_secp256k1_instruction_signatures)
|
|
|
+ .saturating_add(self.num_ed25519_instruction_signatures)
|
|
|
+ }
|
|
|
+
|
|
|
+ /// return the number of transaction signatures
|
|
|
+ pub fn num_transaction_signatures(&self) -> u64 {
|
|
|
+ self.num_transaction_signatures
|
|
|
+ }
|
|
|
+
|
|
|
+ /// return the number of secp256k1 instruction signatures
|
|
|
+ pub fn num_secp256k1_instruction_signatures(&self) -> u64 {
|
|
|
+ self.num_secp256k1_instruction_signatures
|
|
|
+ }
|
|
|
+
|
|
|
+ /// return the number of ed25519 instruction signatures
|
|
|
+ pub fn num_ed25519_instruction_signatures(&self) -> u64 {
|
|
|
+ self.num_ed25519_instruction_signatures
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -559,4 +611,44 @@ mod tests {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ fn test_get_signature_details() {
|
|
|
+ let key0 = Pubkey::new_unique();
|
|
|
+ let key1 = Pubkey::new_unique();
|
|
|
+ let loader_key = Pubkey::new_unique();
|
|
|
+
|
|
|
+ let loader_instr = CompiledInstruction::new(2, &(), vec![0, 1]);
|
|
|
+ let mock_secp256k1_instr = CompiledInstruction::new(3, &[1u8; 10], vec![]);
|
|
|
+ let mock_ed25519_instr = CompiledInstruction::new(4, &[5u8; 10], vec![]);
|
|
|
+
|
|
|
+ let message = SanitizedMessage::try_from(legacy::Message::new_with_compiled_instructions(
|
|
|
+ 2,
|
|
|
+ 1,
|
|
|
+ 2,
|
|
|
+ vec![
|
|
|
+ key0,
|
|
|
+ key1,
|
|
|
+ loader_key,
|
|
|
+ secp256k1_program::id(),
|
|
|
+ ed25519_program::id(),
|
|
|
+ ],
|
|
|
+ Hash::default(),
|
|
|
+ vec![
|
|
|
+ loader_instr,
|
|
|
+ mock_secp256k1_instr.clone(),
|
|
|
+ mock_ed25519_instr,
|
|
|
+ mock_secp256k1_instr,
|
|
|
+ ],
|
|
|
+ ))
|
|
|
+ .unwrap();
|
|
|
+
|
|
|
+ let signature_details = message.get_signature_details();
|
|
|
+ // expect 2 required transaction signatures
|
|
|
+ assert_eq!(2, signature_details.num_transaction_signatures);
|
|
|
+ // expect 2 secp256k1 instruction signatures - 1 for each mock_secp2561k1_instr
|
|
|
+ assert_eq!(2, signature_details.num_secp256k1_instruction_signatures);
|
|
|
+ // expect 5 ed25519 instruction signatures from mock_ed25519_instr
|
|
|
+ assert_eq!(5, signature_details.num_ed25519_instruction_signatures);
|
|
|
+ }
|
|
|
}
|