1use crate::types::H256;
4
5#[derive(Debug, derive_more::Display, PartialEq, Clone)]
7pub enum SigningError {
8 #[display(fmt = "Message has to be a non-zero 32-bytes slice.")]
10 InvalidMessage,
11}
12impl std::error::Error for SigningError {}
13
14#[derive(Debug, derive_more::Display, PartialEq, Clone)]
16pub enum RecoveryError {
17 #[display(fmt = "Message has to be a non-zero 32-bytes slice.")]
19 InvalidMessage,
20 #[display(fmt = "Signature is invalid (check recovery id).")]
22 InvalidSignature,
23}
24impl std::error::Error for RecoveryError {}
25
26#[cfg(feature = "signing")]
27pub use feature_gated::*;
28
29#[cfg(feature = "signing")]
30mod feature_gated {
31 use super::*;
32 use crate::types::Address;
33 pub(crate) use secp256k1::SecretKey;
34 use secp256k1::{
35 recovery::{RecoverableSignature, RecoveryId},
36 Message, PublicKey, Secp256k1,
37 };
38 use std::ops::Deref;
39
40 pub trait Key {
54 fn sign(&self, message: &[u8], chain_id: Option<u64>) -> Result<Signature, SigningError>;
60
61 fn address(&self) -> Address;
63 }
64
65 pub struct SecretKeyRef<'a> {
70 pub(super) key: &'a SecretKey,
71 }
72
73 impl<'a> SecretKeyRef<'a> {
74 pub fn new(key: &'a SecretKey) -> Self {
76 Self { key }
77 }
78 }
79
80 impl<'a> From<&'a SecretKey> for SecretKeyRef<'a> {
81 fn from(key: &'a SecretKey) -> Self {
82 Self::new(key)
83 }
84 }
85
86 impl<'a> Deref for SecretKeyRef<'a> {
87 type Target = SecretKey;
88
89 fn deref(&self) -> &Self::Target {
90 &self.key
91 }
92 }
93
94 impl<T: Deref<Target = SecretKey>> Key for T {
95 fn sign(&self, message: &[u8], chain_id: Option<u64>) -> Result<Signature, SigningError> {
96 let message = Message::from_slice(&message).map_err(|_| SigningError::InvalidMessage)?;
97 let (recovery_id, signature) = Secp256k1::signing_only()
98 .sign_recoverable(&message, self)
99 .serialize_compact();
100
101 let standard_v = recovery_id.to_i32() as u64;
102 let v = if let Some(chain_id) = chain_id {
103 standard_v + 35 + chain_id * 2
105 } else {
106 standard_v + 27
108 };
109 let r = H256::from_slice(&signature[..32]);
110 let s = H256::from_slice(&signature[32..]);
111
112 Ok(Signature { v, r, s })
113 }
114
115 fn address(&self) -> Address {
116 secret_key_address(self)
117 }
118 }
119
120 pub fn recover(message: &[u8], signature: &[u8], recovery_id: i32) -> Result<Address, RecoveryError> {
124 let message = Message::from_slice(message).map_err(|_| RecoveryError::InvalidMessage)?;
125 let recovery_id = RecoveryId::from_i32(recovery_id).map_err(|_| RecoveryError::InvalidSignature)?;
126 let signature =
127 RecoverableSignature::from_compact(&signature, recovery_id).map_err(|_| RecoveryError::InvalidSignature)?;
128 let public_key = Secp256k1::verification_only()
129 .recover(&message, &signature)
130 .map_err(|_| RecoveryError::InvalidSignature)?;
131
132 Ok(public_key_address(&public_key))
133 }
134
135 pub(crate) fn public_key_address(public_key: &PublicKey) -> Address {
143 let public_key = public_key.serialize_uncompressed();
144
145 debug_assert_eq!(public_key[0], 0x04);
146 let hash = keccak256(&public_key[1..]);
147
148 Address::from_slice(&hash[12..])
149 }
150
151 pub(crate) fn secret_key_address(key: &SecretKey) -> Address {
153 let secp = Secp256k1::signing_only();
154 let public_key = PublicKey::from_secret_key(&secp, key);
155 public_key_address(&public_key)
156 }
157}
158
159pub struct Signature {
161 pub v: u64,
163 pub r: H256,
165 pub s: H256,
167}
168
169pub fn keccak256(bytes: &[u8]) -> [u8; 32] {
171 use tiny_keccak::{Hasher, Keccak};
172 let mut output = [0u8; 32];
173 let mut hasher = Keccak::v256();
174 hasher.update(bytes);
175 hasher.finalize(&mut output);
176 output
177}