reth_stateless/
recover_block.rs1use crate::validation::StatelessValidationError;
2use alloc::vec::Vec;
3use alloy_consensus::BlockHeader;
4use alloy_primitives::{Address, Signature, B256};
5use core::ops::Deref;
6use reth_chainspec::EthereumHardforks;
7use reth_ethereum_primitives::{Block, TransactionSigned};
8use reth_primitives_traits::{Block as _, RecoveredBlock};
9use serde::{Deserialize, Serialize};
10use serde_with::{serde_as, Bytes};
11
12#[cfg(all(feature = "k256", feature = "secp256k1"))]
13use k256 as _;
14
15#[serde_as]
17#[derive(Debug, Clone, Serialize, Deserialize)]
18pub struct UncompressedPublicKey(#[serde_as(as = "Bytes")] pub [u8; 65]);
19
20impl Deref for UncompressedPublicKey {
21 type Target = [u8];
22
23 fn deref(&self) -> &Self::Target {
24 &self.0
25 }
26}
27
28pub(crate) fn recover_block_with_public_keys<ChainSpec>(
32 block: Block,
33 public_keys: Vec<UncompressedPublicKey>,
34 chain_spec: &ChainSpec,
35) -> Result<RecoveredBlock<Block>, StatelessValidationError>
36where
37 ChainSpec: EthereumHardforks,
38{
39 if block.body().transactions.len() != public_keys.len() {
40 return Err(StatelessValidationError::Custom(
41 "Number of public keys must match number of transactions",
42 ));
43 }
44
45 let is_homestead = chain_spec.is_homestead_active_at_block(block.header().number());
47
48 let senders = public_keys
50 .iter()
51 .zip(block.body().transactions())
52 .map(|(vk, tx)| verify_and_compute_sender(vk, tx, is_homestead))
53 .collect::<Result<Vec<_>, _>>()?;
54
55 let block_hash = block.hash_slow();
57 Ok(RecoveredBlock::new(block, senders, block_hash))
58}
59
60fn verify_and_compute_sender(
67 vk: &UncompressedPublicKey,
68 tx: &TransactionSigned,
69 is_homestead: bool,
70) -> Result<Address, StatelessValidationError> {
71 let sig = tx.signature();
72
73 let sig_is_normalized = sig.normalize_s().is_none();
75 if is_homestead && !sig_is_normalized {
76 return Err(StatelessValidationError::HomesteadSignatureNotNormalized);
77 }
78 let sig_hash = tx.signature_hash();
79 #[cfg(all(feature = "k256", feature = "secp256k1"))]
80 {
81 let _ = verify_and_compute_sender_unchecked_k256;
82 }
83 #[cfg(feature = "secp256k1")]
84 {
85 verify_and_compute_sender_unchecked_secp256k1(vk, sig, sig_hash)
86 }
87 #[cfg(all(feature = "k256", not(feature = "secp256k1")))]
88 {
89 verify_and_compute_sender_unchecked_k256(vk, sig, sig_hash)
90 }
91 #[cfg(not(any(feature = "secp256k1", feature = "k256")))]
92 {
93 let _ = vk;
94 let _ = tx;
95 let _: B256 = sig_hash;
96 let _: &Signature = sig;
97
98 unimplemented!("Must choose either k256 or secp256k1 feature")
99 }
100}
101#[cfg(feature = "k256")]
102fn verify_and_compute_sender_unchecked_k256(
103 vk: &UncompressedPublicKey,
104 sig: &Signature,
105 sig_hash: B256,
106) -> Result<Address, StatelessValidationError> {
107 use k256::ecdsa::{signature::hazmat::PrehashVerifier, VerifyingKey};
108
109 let vk =
110 VerifyingKey::from_sec1_bytes(vk).map_err(|_| StatelessValidationError::SignerRecovery)?;
111
112 sig.to_k256()
113 .and_then(|sig| vk.verify_prehash(sig_hash.as_slice(), &sig))
114 .map_err(|_| StatelessValidationError::SignerRecovery)?;
115
116 Ok(Address::from_public_key(&vk))
117}
118
119#[cfg(feature = "secp256k1")]
120fn verify_and_compute_sender_unchecked_secp256k1(
121 vk: &UncompressedPublicKey,
122 sig: &Signature,
123 sig_hash: B256,
124) -> Result<Address, StatelessValidationError> {
125 use secp256k1::{ecdsa::Signature as SecpSignature, Message, PublicKey, SECP256K1};
126
127 let public_key =
128 PublicKey::from_slice(vk).map_err(|_| StatelessValidationError::SignerRecovery)?;
129
130 let mut sig_bytes = [0u8; 64];
131 sig_bytes[0..32].copy_from_slice(&sig.r().to_be_bytes::<32>());
132 sig_bytes[32..64].copy_from_slice(&sig.s().to_be_bytes::<32>());
133
134 let signature = SecpSignature::from_compact(&sig_bytes)
135 .map_err(|_| StatelessValidationError::SignerRecovery)?;
136
137 let message = Message::from_digest(sig_hash.0);
138 SECP256K1
139 .verify_ecdsa(&message, &signature, &public_key)
140 .map_err(|_| StatelessValidationError::SignerRecovery)?;
141
142 Ok(Address::from_raw_public_key(&vk[1..]))
143}