diff --git a/Cargo.lock b/Cargo.lock index 67248d75..9795a618 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1279,6 +1279,7 @@ dependencies = [ "convert_case", "elliptic-curve", "ethabi", + "fastrlp", "generic-array 0.14.5", "hex", "hex-literal", @@ -1512,6 +1513,31 @@ dependencies = [ "instant", ] +[[package]] +name = "fastrlp" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6c60b758dc5bf92743e1b863ac88b84a4750bd096b19c2f524359659dc1f1ac" +dependencies = [ + "arrayvec 0.7.2", + "auto_impl", + "bytes", + "ethereum-types", + "fastrlp-derive", +] + +[[package]] +name = "fastrlp-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9499f20a2fa1a744422de24d1b4d1ec58f240147de1d0a3ceacadf2e240b4fc2" +dependencies = [ + "bytes", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "ff" version = "0.11.0" diff --git a/ethers-core/Cargo.toml b/ethers-core/Cargo.toml index 394d228b..e5f3dd2b 100644 --- a/ethers-core/Cargo.toml +++ b/ethers-core/Cargo.toml @@ -10,6 +10,7 @@ repository = "https://github.com/gakonst/ethers-rs" keywords = ["ethereum", "web3", "celo", "ethers"] [dependencies] +fastrlp = { version = "0.1.2", features = ["std", "derive", "ethereum-types"] } rlp = { version = "0.5.0", default-features = false, features = ["std"] } ethabi = { version = "17.1.0", default-features = false, features = ["full-serde", "rlp"] } arrayvec = { version = "0.7.2", default-features = false } diff --git a/ethers-core/src/types/signature.rs b/ethers-core/src/types/signature.rs index 5cddf4e7..95c3f324 100644 --- a/ethers-core/src/types/signature.rs +++ b/ethers-core/src/types/signature.rs @@ -4,6 +4,7 @@ use crate::{ utils::hash_message, }; +use fastrlp::Decodable; use serde::{Deserialize, Serialize}; use std::{convert::TryFrom, fmt, str::FromStr}; @@ -53,7 +54,7 @@ pub enum RecoveryMessage { Hash(H256), } -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Copy)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Copy, Hash)] /// An ECDSA signature pub struct Signature { /// R value @@ -141,6 +142,29 @@ impl Signature { pub fn to_vec(&self) -> Vec { self.into() } + + /// Decodes a signature from RLP bytes, assuming no RLP header + pub(crate) fn decode_signature(buf: &mut &[u8]) -> Result { + let v = u64::decode(buf)?; + Ok(Self { r: U256::decode(buf)?, s: U256::decode(buf)?, v }) + } +} + +impl fastrlp::Decodable for Signature { + fn decode(buf: &mut &[u8]) -> Result { + Self::decode_signature(buf) + } +} + +impl fastrlp::Encodable for Signature { + fn length(&self) -> usize { + self.r.length() + self.s.length() + self.v.length() + } + fn encode(&self, out: &mut dyn bytes::BufMut) { + self.v.encode(out); + self.r.encode(out); + self.s.encode(out); + } } fn normalize_recovery_id(v: u64) -> u8 {