Skip to content

Commit

Permalink
fix(levm): change error to empty bytes in ecrecover (#1570)
Browse files Browse the repository at this point in the history
**Motivation**

We should return empty bytes when there are errors in the `libsecp256k1`
functions. Errors should only be returned in cases of analysis or
cutting.

**Description**

Previously, we returned `PrecompileError::ParsingInputError` when
`Message::parse_slice` or `Signature::parse_standard_slice` failed.
Also, we were inconsistent, sometimes returning an error and other times
returning empty bytes.

Now, we return `Bytes::new()` whenever the `libsecp256k1` functions
fail.
  • Loading branch information
damiramirez authored Dec 27, 2024
1 parent 8c8d61f commit bc8152f
Showing 1 changed file with 13 additions and 15 deletions.
28 changes: 13 additions & 15 deletions crates/vm/levm/src/precompiles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,9 @@ pub fn ecrecover(

// Parse the input elements, first as a slice of bytes and then as an specific type of the crate
let hash = calldata.get(0..32).ok_or(InternalError::SlicingError)?;
let message = Message::parse_slice(hash).map_err(|_| PrecompileError::ParsingInputError)?;
let Ok(message) = Message::parse_slice(hash) else {
return Ok(Bytes::new());
};

let v: U256 = calldata
.get(32..64)
Expand All @@ -177,26 +179,22 @@ pub fn ecrecover(
}

let v = u8::try_from(v).map_err(|_| InternalError::ConversionError)?;
let recovery_id = match RecoveryId::parse_rpc(v) {
Ok(id) => id,
Err(_) => {
return Ok(Bytes::new());
}
let Ok(recovery_id) = RecoveryId::parse_rpc(v) else {
return Ok(Bytes::new());
};

// signature is made up of the parameters r and s
let sig = calldata.get(64..128).ok_or(InternalError::SlicingError)?;
let signature =
Signature::parse_standard_slice(sig).map_err(|_| PrecompileError::ParsingInputError)?;
let Ok(signature) = Signature::parse_standard_slice(sig) else {
return Ok(Bytes::new());
};

// Recover the address using secp256k1
let mut public_key = match libsecp256k1::recover(&message, &signature, &recovery_id) {
Ok(id) => id,
Err(_) => {
return Ok(Bytes::new());
}
}
.serialize();
let Ok(public_key) = libsecp256k1::recover(&message, &signature, &recovery_id) else {
return Ok(Bytes::new());
};

let mut public_key = public_key.serialize();

// We need to take the 64 bytes from the public key (discarding the first pos of the slice)
keccak256(&mut public_key[1..65]);
Expand Down

0 comments on commit bc8152f

Please sign in to comment.