Cleanup and standardize precompiles (#19918)

This commit is contained in:
Jack May 2021-09-17 11:36:57 -07:00 committed by GitHub
parent 99f5684dc4
commit fc2bf2d3b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 250 additions and 156 deletions

View File

@ -1090,7 +1090,7 @@ fn test_program_bpf_invoke_sanity() {
result.unwrap_err(),
TransactionError::InstructionError(0, InstructionError::ProgramFailedToComplete)
);
}
}
}
#[cfg(feature = "bpf_rust")]

View File

@ -1,27 +1,9 @@
#![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 ed25519_dalek::{ed25519::signature::Signature, Signer, Verifier};
use thiserror::Error;
#[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"
}
}
use std::sync::Arc;
pub const PUBKEY_SERIALIZED_SIZE: usize = 32;
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 {
return Err(Ed25519Error::InvalidInstructionDataSize);
return Err(PrecompileError::InvalidInstructionDataSize);
}
let num_signatures = data[0] as usize;
if num_signatures == 0 && data.len() > SIGNATURE_OFFSETS_START {
return Err(Ed25519Error::InvalidInstructionDataSize);
return Err(PrecompileError::InvalidInstructionDataSize);
}
let expected_data_size = num_signatures
.saturating_mul(SIGNATURE_OFFSETS_SERIALIZED_SIZE)
.saturating_add(SIGNATURE_OFFSETS_START);
if data.len() < expected_data_size {
return Err(Ed25519Error::InvalidInstructionDataSize);
return Err(PrecompileError::InvalidInstructionDataSize);
}
for i in 0..num_signatures {
let start = i
@ -117,23 +103,23 @@ pub fn verify_signatures(data: &[u8], instruction_datas: &[&[u8]]) -> Result<(),
// bytemuck wants structures aligned
let offsets: &Ed25519SignatureOffsets = bytemuck::try_from_bytes(&data[start..end])
.map_err(|_| Ed25519Error::InvalidDataOffsets)?;
.map_err(|_| PrecompileError::InvalidDataOffsets)?;
// Parse out signature
let signature_index = offsets.signature_instruction_index as usize;
if signature_index >= instruction_datas.len() {
return Err(Ed25519Error::InvalidDataOffsets);
return Err(PrecompileError::InvalidDataOffsets);
}
let signature_instruction = instruction_datas[signature_index];
let sig_start = offsets.signature_offset as usize;
let sig_end = sig_start.saturating_add(SIGNATURE_SERIALIZED_SIZE);
if sig_end >= signature_instruction.len() {
return Err(Ed25519Error::InvalidDataOffsets);
return Err(PrecompileError::InvalidDataOffsets);
}
let signature =
ed25519_dalek::Signature::from_bytes(&signature_instruction[sig_start..sig_end])
.map_err(|_| Ed25519Error::InvalidSignature)?;
.map_err(|_| PrecompileError::InvalidSignature)?;
// Parse out pubkey
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)
.map_err(|_| Ed25519Error::InvalidPublicKey)?;
.map_err(|_| PrecompileError::InvalidPublicKey)?;
// Parse out message
let message = get_data_slice(
@ -156,7 +142,7 @@ pub fn verify_signatures(data: &[u8], instruction_datas: &[&[u8]]) -> Result<(),
publickey
.verify(message, &signature)
.map_err(|_| Ed25519Error::InvalidSignature)?;
.map_err(|_| PrecompileError::InvalidSignature)?;
}
Ok(())
}
@ -166,16 +152,16 @@ fn get_data_slice<'a>(
instruction_index: u16,
offset_start: u16,
size: usize,
) -> Result<&'a [u8], Ed25519Error> {
) -> Result<&'a [u8], PrecompileError> {
let signature_index = instruction_index as usize;
if signature_index >= instruction_datas.len() {
return Err(Ed25519Error::InvalidDataOffsets);
return Err(PrecompileError::InvalidDataOffsets);
}
let signature_instruction = &instruction_datas[signature_index];
let start = offset_start as usize;
let end = start.saturating_add(size);
if end > signature_instruction.len() {
return Err(Ed25519Error::InvalidDataOffsets);
return Err(PrecompileError::InvalidDataOffsets);
}
Ok(&instruction_datas[signature_index][start..end])
@ -188,7 +174,7 @@ pub mod test {
fn test_case(
num_signatures: u16,
offsets: &Ed25519SignatureOffsets,
) -> Result<(), Ed25519Error> {
) -> Result<(), PrecompileError> {
assert_eq!(
bytemuck::bytes_of(offsets).len(),
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[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]
@ -212,8 +202,12 @@ pub mod test {
instruction_data.truncate(instruction_data.len() - 1);
assert_eq!(
verify_signatures(&instruction_data, &[&[0u8; 100]]),
Err(Ed25519Error::InvalidInstructionDataSize)
verify(
&instruction_data,
&[&[0u8; 100]],
&Arc::new(FeatureSet::all_enabled()),
),
Err(PrecompileError::InvalidInstructionDataSize)
);
let offsets = Ed25519SignatureOffsets {
@ -222,7 +216,7 @@ pub mod test {
};
assert_eq!(
test_case(1, &offsets),
Err(Ed25519Error::InvalidDataOffsets)
Err(PrecompileError::InvalidDataOffsets)
);
let offsets = Ed25519SignatureOffsets {
@ -231,7 +225,7 @@ pub mod test {
};
assert_eq!(
test_case(1, &offsets),
Err(Ed25519Error::InvalidDataOffsets)
Err(PrecompileError::InvalidDataOffsets)
);
let offsets = Ed25519SignatureOffsets {
@ -240,7 +234,7 @@ pub mod test {
};
assert_eq!(
test_case(1, &offsets),
Err(Ed25519Error::InvalidDataOffsets)
Err(PrecompileError::InvalidDataOffsets)
);
}
@ -251,7 +245,10 @@ pub mod test {
message_data_size: 1,
..Ed25519SignatureOffsets::default()
};
assert_eq!(test_case(1, &offsets), Err(Ed25519Error::InvalidSignature));
assert_eq!(
test_case(1, &offsets),
Err(PrecompileError::InvalidSignature)
);
let offsets = Ed25519SignatureOffsets {
message_data_offset: 100,
@ -260,7 +257,7 @@ pub mod test {
};
assert_eq!(
test_case(1, &offsets),
Err(Ed25519Error::InvalidDataOffsets)
Err(PrecompileError::InvalidDataOffsets)
);
let offsets = Ed25519SignatureOffsets {
@ -270,7 +267,7 @@ pub mod test {
};
assert_eq!(
test_case(1, &offsets),
Err(Ed25519Error::InvalidDataOffsets)
Err(PrecompileError::InvalidDataOffsets)
);
let offsets = Ed25519SignatureOffsets {
@ -280,7 +277,7 @@ pub mod test {
};
assert_eq!(
test_case(1, &offsets),
Err(Ed25519Error::InvalidDataOffsets)
Err(PrecompileError::InvalidDataOffsets)
);
}
@ -292,7 +289,7 @@ pub mod test {
};
assert_eq!(
test_case(1, &offsets),
Err(Ed25519Error::InvalidDataOffsets)
Err(PrecompileError::InvalidDataOffsets)
);
let offsets = Ed25519SignatureOffsets {
@ -301,7 +298,7 @@ pub mod test {
};
assert_eq!(
test_case(1, &offsets),
Err(Ed25519Error::InvalidDataOffsets)
Err(PrecompileError::InvalidDataOffsets)
);
}
@ -313,7 +310,7 @@ pub mod test {
};
assert_eq!(
test_case(1, &offsets),
Err(Ed25519Error::InvalidDataOffsets)
Err(PrecompileError::InvalidDataOffsets)
);
let offsets = Ed25519SignatureOffsets {
@ -322,7 +319,7 @@ pub mod test {
};
assert_eq!(
test_case(1, &offsets),
Err(Ed25519Error::InvalidDataOffsets)
Err(PrecompileError::InvalidDataOffsets)
);
}
}

View File

@ -36,6 +36,7 @@ pub mod nonce_account;
pub mod nonce_keyed_account;
pub mod packet;
pub mod poh_config;
pub mod precompiles;
pub mod process_instruction;
pub mod program_utils;
pub mod pubkey;

117
sdk/src/precompiles.rs Normal file
View 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(())
}

View File

@ -1,16 +1,13 @@
#![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 serde_derive::{Deserialize, Serialize};
#[derive(Debug, PartialEq)]
pub enum Secp256k1Error {
InvalidSignature,
InvalidRecoveryId,
InvalidDataOffsets,
InvalidInstructionDataSize,
}
use std::sync::Arc;
pub const HASHED_PUBKEY_SERIALIZED_SIZE: usize = 20;
pub const SIGNATURE_SERIALIZED_SIZE: usize = 64;
@ -99,27 +96,27 @@ pub fn construct_eth_pubkey(
addr
}
pub fn verify_eth_addresses(
pub fn verify(
data: &[u8],
instruction_datas: &[&[u8]],
libsecp256k1_0_5_upgrade_enabled: bool,
libsecp256k1_fail_on_bad_count: bool,
) -> Result<(), Secp256k1Error> {
feature_set: &Arc<FeatureSet>,
) -> Result<(), PrecompileError> {
if data.is_empty() {
return Err(Secp256k1Error::InvalidInstructionDataSize);
return Err(PrecompileError::InvalidInstructionDataSize);
}
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
// correct, fail the instruction to catch probable invalid secp256k1
// instruction construction.
return Err(Secp256k1Error::InvalidInstructionDataSize);
return Err(PrecompileError::InvalidInstructionDataSize);
}
let expected_data_size = count
.saturating_mul(SIGNATURE_OFFSETS_SERIALIZED_SIZE)
.saturating_add(1);
if data.len() < expected_data_size {
return Err(Secp256k1Error::InvalidInstructionDataSize);
return Err(PrecompileError::InvalidInstructionDataSize);
}
for i in 0..count {
let start = i
@ -128,21 +125,21 @@ pub fn verify_eth_addresses(
let end = start.saturating_add(SIGNATURE_OFFSETS_SERIALIZED_SIZE);
let offsets: SecpSignatureOffsets = bincode::deserialize(&data[start..end])
.map_err(|_| Secp256k1Error::InvalidSignature)?;
.map_err(|_| PrecompileError::InvalidSignature)?;
// Parse out signature
let signature_index = offsets.signature_instruction_index as usize;
if signature_index >= instruction_datas.len() {
return Err(Secp256k1Error::InvalidInstructionDataSize);
return Err(PrecompileError::InvalidInstructionDataSize);
}
let signature_instruction = instruction_datas[signature_index];
let sig_start = offsets.signature_offset as usize;
let sig_end = sig_start.saturating_add(SIGNATURE_SERIALIZED_SIZE);
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(
&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])
.map_err(|_| Secp256k1Error::InvalidRecoveryId)?;
.map_err(|_| PrecompileError::InvalidRecoveryId)?;
// Parse out pubkey
let eth_address_slice = get_data_slice(
@ -182,11 +179,11 @@ pub fn verify_eth_addresses(
&signature,
&recovery_id,
)
.map_err(|_| Secp256k1Error::InvalidSignature)?;
.map_err(|_| PrecompileError::InvalidSignature)?;
let eth_address = construct_eth_pubkey(&pubkey);
if eth_address_slice != eth_address {
return Err(Secp256k1Error::InvalidSignature);
return Err(PrecompileError::InvalidSignature);
}
}
Ok(())
@ -197,16 +194,16 @@ fn get_data_slice<'a>(
instruction_index: u8,
offset_start: u16,
size: usize,
) -> Result<&'a [u8], Secp256k1Error> {
) -> Result<&'a [u8], PrecompileError> {
let signature_index = instruction_index as usize;
if signature_index >= instruction_datas.len() {
return Err(Secp256k1Error::InvalidDataOffsets);
return Err(PrecompileError::InvalidDataOffsets);
}
let signature_instruction = &instruction_datas[signature_index];
let start = offset_start as usize;
let end = start.saturating_add(size);
if end > signature_instruction.len() {
return Err(Secp256k1Error::InvalidSignature);
return Err(PrecompileError::InvalidSignature);
}
Ok(&instruction_datas[signature_index][start..end])
@ -216,13 +213,23 @@ fn get_data_slice<'a>(
pub mod test {
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];
instruction_data[0] = num_signatures;
let writer = std::io::Cursor::new(&mut instruction_data[1..]);
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]
@ -235,10 +242,17 @@ pub mod test {
let writer = std::io::Cursor::new(&mut instruction_data[1..]);
bincode::serialize_into(writer, &offsets).unwrap();
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!(
verify_eth_addresses(&instruction_data, &[&[0u8; 100]], false, true),
Err(Secp256k1Error::InvalidInstructionDataSize)
verify(&instruction_data, &[&[0u8; 100]], &Arc::new(feature_set)),
Err(PrecompileError::InvalidInstructionDataSize)
);
let offsets = SecpSignatureOffsets {
@ -247,7 +261,7 @@ pub mod test {
};
assert_eq!(
test_case(1, &offsets),
Err(Secp256k1Error::InvalidInstructionDataSize)
Err(PrecompileError::InvalidInstructionDataSize)
);
let offsets = SecpSignatureOffsets {
@ -256,7 +270,7 @@ pub mod test {
};
assert_eq!(
test_case(1, &offsets),
Err(Secp256k1Error::InvalidDataOffsets)
Err(PrecompileError::InvalidDataOffsets)
);
let offsets = SecpSignatureOffsets {
@ -265,7 +279,7 @@ pub mod test {
};
assert_eq!(
test_case(1, &offsets),
Err(Secp256k1Error::InvalidDataOffsets)
Err(PrecompileError::InvalidDataOffsets)
);
}
@ -278,7 +292,7 @@ pub mod test {
};
assert_eq!(
test_case(1, &offsets),
Err(Secp256k1Error::InvalidSignature)
Err(PrecompileError::InvalidSignature)
);
let offsets = SecpSignatureOffsets {
@ -288,7 +302,7 @@ pub mod test {
};
assert_eq!(
test_case(1, &offsets),
Err(Secp256k1Error::InvalidSignature)
Err(PrecompileError::InvalidSignature)
);
let offsets = SecpSignatureOffsets {
@ -298,7 +312,7 @@ pub mod test {
};
assert_eq!(
test_case(1, &offsets),
Err(Secp256k1Error::InvalidSignature)
Err(PrecompileError::InvalidSignature)
);
let offsets = SecpSignatureOffsets {
@ -308,7 +322,7 @@ pub mod test {
};
assert_eq!(
test_case(1, &offsets),
Err(Secp256k1Error::InvalidSignature)
Err(PrecompileError::InvalidSignature)
);
}
@ -320,7 +334,7 @@ pub mod test {
};
assert_eq!(
test_case(1, &offsets),
Err(Secp256k1Error::InvalidSignature)
Err(PrecompileError::InvalidSignature)
);
let offsets = SecpSignatureOffsets {
@ -329,7 +343,7 @@ pub mod test {
};
assert_eq!(
test_case(1, &offsets),
Err(Secp256k1Error::InvalidSignature)
Err(PrecompileError::InvalidSignature)
);
}
@ -341,7 +355,7 @@ pub mod test {
};
assert_eq!(
test_case(1, &offsets),
Err(Secp256k1Error::InvalidSignature)
Err(PrecompileError::InvalidSignature)
);
let offsets = SecpSignatureOffsets {
@ -350,7 +364,7 @@ pub mod test {
};
assert_eq!(
test_case(1, &offsets),
Err(Secp256k1Error::InvalidSignature)
Err(PrecompileError::InvalidSignature)
);
}
@ -363,9 +377,17 @@ pub mod test {
instruction_data[0] = 0;
let writer = std::io::Cursor::new(&mut instruction_data[1..]);
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!(
verify_eth_addresses(&instruction_data, &[&[0u8; 100]], false, true),
Err(Secp256k1Error::InvalidInstructionDataSize)
verify(&instruction_data, &[&[0u8; 100]], &Arc::new(feature_set)),
Err(PrecompileError::InvalidInstructionDataSize)
);
}
}

View File

@ -4,15 +4,14 @@
use {
crate::{
ed25519_instruction::verify_signatures,
hash::Hash,
instruction::{CompiledInstruction, Instruction, InstructionError},
message::{Message, SanitizeMessageError},
nonce::NONCED_TX_MARKER_IX_INDEX,
precompiles::verify_if_precompile,
program_utils::limited_deserialize,
pubkey::Pubkey,
sanitize::{Sanitize, SanitizeError},
secp256k1_instruction::verify_eth_addresses,
short_vec,
signature::{Signature, SignerError},
signers::Signers,
@ -433,6 +432,7 @@ impl Transaction {
.collect()
}
/// Verify the precompiled programs in this transaction
pub fn verify_precompiles(&self, feature_set: &Arc<feature_set::FeatureSet>) -> Result<()> {
for instruction in &self.message().instructions {
// The Transaction may not be sanitized at this point
@ -440,34 +440,14 @@ impl Transaction {
return Err(TransactionError::AccountNotFound);
}
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
.message()
.instructions
.iter()
.map(|instruction| instruction.data.as_ref())
.collect();
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)?;
}
verify_if_precompile(
program_id,
instruction,
&self.message().instructions,
feature_set,
)
.map_err(|_| TransactionError::InvalidAccountIndex)?;
}
Ok(())
}

View File

@ -2,15 +2,13 @@
use {
crate::{
ed25519_instruction::verify_signatures,
hash::Hash,
message::{v0, MappedAddresses, MappedMessage, SanitizedMessage, VersionedMessage},
nonce::NONCED_TX_MARKER_IX_INDEX,
precompiles::verify_if_precompile,
program_utils::limited_deserialize,
pubkey::Pubkey,
sanitize::Sanitize,
secp256k1_instruction::verify_eth_addresses,
secp256k1_program,
signature::Signature,
solana_sdk::feature_set,
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<()> {
for (program_id, instruction) in self.message.program_instructions_iter() {
if secp256k1_program::check_id(program_id) {
let instruction_datas: Vec<_> = self
.message
.instructions()
.iter()
.map(|instruction| instruction.data.as_ref())
.collect();
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)?;
}
verify_if_precompile(
program_id,
instruction,
self.message().instructions(),
feature_set,
)
.map_err(|_| TransactionError::InvalidAccountIndex)?;
}
Ok(())
}