Skip to content

Commit

Permalink
chore: improve clique signer recovery error (#5613)
Browse files Browse the repository at this point in the history
  • Loading branch information
mattsse authored Nov 28, 2023
1 parent 43d1f5a commit ae6f1e3
Showing 1 changed file with 22 additions and 4 deletions.
26 changes: 22 additions & 4 deletions crates/primitives/src/revm/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,26 +92,44 @@ pub fn fill_block_env_with_coinbase(
/// Return the coinbase address for the given header and chain spec.
pub fn block_coinbase(chain_spec: &ChainSpec, header: &Header, after_merge: bool) -> Address {
if chain_spec.chain == Chain::goerli() && !after_merge {
recover_header_signer(header).expect("failed to recover signer")
recover_header_signer(header).unwrap_or_else(|err| {
panic!(
"Failed to recover goerli Clique Consensus signer from header ({}, {}) using extradata {}: {:?}",
header.number, header.hash_slow(), header.extra_data, err
)
})
} else {
header.beneficiary
}
}

/// Error type for recovering Clique signer from a header.
#[derive(Debug, thiserror::Error)]
pub enum CliqueSignerRecoveryError {
/// Header extradata is too short.
#[error("Invalid extra data length")]
InvalidExtraData,
/// Recovery failed.
#[error("Invalid signature: {0}")]
InvalidSignature(#[from] secp256k1::Error),
}

/// Recover the account from signed header per clique consensus rules.
pub fn recover_header_signer(header: &Header) -> Option<Address> {
pub fn recover_header_signer(header: &Header) -> Result<Address, CliqueSignerRecoveryError> {
let extra_data_len = header.extra_data.len();
// Fixed number of extra-data suffix bytes reserved for signer signature.
// 65 bytes fixed as signatures are based on the standard secp256k1 curve.
// Filled with zeros on genesis block.
let signature_start_byte = extra_data_len - 65;
let signature: [u8; 65] = header.extra_data[signature_start_byte..].try_into().ok()?;
let signature: [u8; 65] = header.extra_data[signature_start_byte..]
.try_into()
.map_err(|_| CliqueSignerRecoveryError::InvalidExtraData)?;
let seal_hash = {
let mut header_to_seal = header.clone();
header_to_seal.extra_data = Bytes::from(header.extra_data[..signature_start_byte].to_vec());
header_to_seal.hash_slow()
};
recover_signer(&signature, &seal_hash.0).ok()
recover_signer(&signature, &seal_hash.0).map_err(CliqueSignerRecoveryError::InvalidSignature)
}

/// Returns a new [TxEnv] filled with the transaction's data.
Expand Down

0 comments on commit ae6f1e3

Please sign in to comment.