1#![allow(clippy::missing_const_for_fn)] use crate::{B256, U256, hex, normalize_v, signature::SignatureError, uint};
4use alloc::vec::Vec;
5use core::{fmt::Display, str::FromStr};
6
7#[cfg(any(feature = "k256", feature = "secp256k1"))]
8use crate::Address;
9
10const SECP256K1N_ORDER: U256 =
12 uint!(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141_U256);
13
14#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
16#[cfg_attr(feature = "diesel", derive(diesel::AsExpression, diesel::FromSqlRow))]
17#[cfg_attr(feature = "diesel", diesel(sql_type = diesel::sql_types::Binary))]
18pub struct Signature {
19 y_parity: bool,
20 r: U256,
21 s: U256,
22}
23
24impl Display for Signature {
25 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
26 write!(f, "0x{}", hex::encode(self.as_bytes()))
27 }
28}
29
30impl TryFrom<&[u8]> for Signature {
31 type Error = SignatureError;
32
33 fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
37 Self::from_raw(bytes)
38 }
39}
40
41impl FromStr for Signature {
42 type Err = SignatureError;
43
44 fn from_str(s: &str) -> Result<Self, Self::Err> {
45 Self::from_raw_array(&hex::decode_to_array(s)?)
46 }
47}
48
49impl From<&Signature> for [u8; 65] {
50 #[inline]
51 fn from(value: &Signature) -> [u8; 65] {
52 value.as_bytes()
53 }
54}
55
56impl From<Signature> for [u8; 65] {
57 #[inline]
58 fn from(value: Signature) -> [u8; 65] {
59 value.as_bytes()
60 }
61}
62
63impl From<&Signature> for Vec<u8> {
64 #[inline]
65 fn from(value: &Signature) -> Self {
66 value.as_bytes().to_vec()
67 }
68}
69
70impl From<Signature> for Vec<u8> {
71 #[inline]
72 fn from(value: Signature) -> Self {
73 value.as_bytes().to_vec()
74 }
75}
76
77#[cfg(feature = "k256")]
78impl From<(k256::ecdsa::Signature, k256::ecdsa::RecoveryId)> for Signature {
79 fn from(value: (k256::ecdsa::Signature, k256::ecdsa::RecoveryId)) -> Self {
80 Self::from_signature_and_parity(value.0, value.1.is_y_odd())
81 }
82}
83
84#[cfg(feature = "secp256k1")]
85impl From<secp256k1::ecdsa::RecoverableSignature> for Signature {
86 fn from(value: secp256k1::ecdsa::RecoverableSignature) -> Self {
87 let (recid, bytes) = value.serialize_compact();
88 let r = U256::from_be_slice(&bytes[..32]);
89 let s = U256::from_be_slice(&bytes[32..]);
90 let v = matches!(
91 recid,
92 secp256k1::ecdsa::RecoveryId::One | secp256k1::ecdsa::RecoveryId::Three
93 );
94 Self { y_parity: v, r, s }
95 }
96}
97
98#[cfg(feature = "k256")]
99impl TryFrom<Signature> for k256::ecdsa::Signature {
100 type Error = k256::ecdsa::Error;
101
102 fn try_from(value: Signature) -> Result<Self, Self::Error> {
103 value.to_k256()
104 }
105}
106
107#[cfg(feature = "rlp")]
108impl Signature {
109 pub fn decode_rlp_vrs(
113 buf: &mut &[u8],
114 decode_parity: impl FnOnce(&mut &[u8]) -> alloy_rlp::Result<bool>,
115 ) -> Result<Self, alloy_rlp::Error> {
116 use alloy_rlp::Decodable;
117
118 let parity = decode_parity(buf)?;
119 let r = Decodable::decode(buf)?;
120 let s = Decodable::decode(buf)?;
121
122 Ok(Self::new(r, s, parity))
123 }
124}
125
126impl Signature {
127 #[inline]
129 pub const fn new(r: U256, s: U256, y_parity: bool) -> Self {
130 Self { r, s, y_parity }
131 }
132
133 #[inline]
138 pub fn from_raw(bytes: &[u8]) -> Result<Self, SignatureError> {
139 Self::from_raw_array(
140 bytes.try_into().map_err(|_| SignatureError::FromBytes("expected exactly 65 bytes"))?,
141 )
142 }
143
144 #[inline]
148 pub fn from_raw_array(bytes: &[u8; 65]) -> Result<Self, SignatureError> {
149 let [bytes @ .., v] = bytes;
150 let v = *v as u64;
151 let Some(parity) = normalize_v(v) else { return Err(SignatureError::InvalidParity(v)) };
152 Ok(Self::from_bytes_and_parity(bytes, parity))
153 }
154
155 #[inline]
161 #[track_caller]
162 pub fn from_bytes_and_parity(bytes: &[u8], parity: bool) -> Self {
163 let (r_bytes, s_bytes) = bytes[..64].split_at(32);
164 let r = U256::from_be_slice(r_bytes);
165 let s = U256::from_be_slice(s_bytes);
166 Self::new(r, s, parity)
167 }
168
169 #[inline]
174 pub fn as_bytes(&self) -> [u8; 65] {
175 let mut sig = [0u8; 65];
176 sig[..32].copy_from_slice(&self.r.to_be_bytes::<32>());
177 sig[32..64].copy_from_slice(&self.s.to_be_bytes::<32>());
178 sig[64] = self.v_byte();
179 sig
180 }
181
182 #[inline]
189 pub fn as_rsy(&self) -> [u8; 65] {
190 let mut sig = [0u8; 65];
191 sig[..32].copy_from_slice(&self.r.to_be_bytes::<32>());
192 sig[32..64].copy_from_slice(&self.s.to_be_bytes::<32>());
193 sig[64] = self.y_parity as u8;
194 sig
195 }
196
197 pub fn from_erc2098(bytes: &[u8]) -> Self {
208 let (r_bytes, y_and_s_bytes) = bytes[..64].split_at(32);
209 let r = U256::from_be_slice(r_bytes);
210 let y_and_s = U256::from_be_slice(y_and_s_bytes);
211 let y_parity = y_and_s.bit(255);
212 let mut s = y_and_s;
213 s.set_bit(255, false);
214 Self { y_parity, r, s }
215 }
216
217 pub fn as_erc2098(&self) -> [u8; 64] {
224 let normalized = self.normalized_s();
225 let mut sig = [0u8; 64];
229 sig[..32].copy_from_slice(&normalized.r().to_be_bytes::<32>());
230 sig[32..64].copy_from_slice(&normalized.s().to_be_bytes::<32>());
231 debug_assert_eq!(sig[32] >> 7, 0, "top bit of s should be 0");
232 sig[32] |= (normalized.y_parity as u8) << 7;
233 sig
234 }
235
236 #[inline]
238 pub fn with_parity(mut self, v: bool) -> Self {
239 self.y_parity = v;
240 self
241 }
242
243 #[cfg(feature = "k256")]
245 #[inline]
246 pub fn to_k256(self) -> Result<k256::ecdsa::Signature, k256::ecdsa::Error> {
247 k256::ecdsa::Signature::from_scalars(self.r.to_be_bytes(), self.s.to_be_bytes())
248 }
249
250 #[cfg(feature = "secp256k1")]
252 #[inline]
253 pub fn to_secp256k1(&self) -> Result<secp256k1::ecdsa::RecoverableSignature, secp256k1::Error> {
254 let mut bytes = [0u8; 64];
255 bytes[..32].copy_from_slice(&self.r.to_be_bytes::<32>());
256 bytes[32..].copy_from_slice(&self.s.to_be_bytes::<32>());
257 secp256k1::ecdsa::RecoverableSignature::from_compact(&bytes, self.secp256k1_recid())
258 }
259
260 #[cfg(feature = "k256")]
262 pub fn from_signature_and_parity(sig: k256::ecdsa::Signature, v: bool) -> Self {
263 let r = U256::from_be_slice(sig.r().to_bytes().as_ref());
264 let s = U256::from_be_slice(sig.s().to_bytes().as_ref());
265 Self { y_parity: v, r, s }
266 }
267
268 #[inline]
271 pub fn from_scalars_and_parity(r: B256, s: B256, parity: bool) -> Self {
272 Self::new(U256::from_be_bytes(r.0), U256::from_be_bytes(s.0), parity)
273 }
274
275 #[inline]
282 pub fn normalize_s(&self) -> Option<Self> {
283 let s = self.s();
284 if s > SECP256K1N_ORDER >> 1 {
285 Some(Self { y_parity: !self.y_parity, r: self.r, s: SECP256K1N_ORDER - s })
286 } else {
287 None
288 }
289 }
290
291 #[inline]
298 pub fn normalized_s(self) -> Self {
299 self.normalize_s().unwrap_or(self)
300 }
301
302 #[cfg(feature = "k256")]
304 #[inline]
305 pub fn recid(&self) -> k256::ecdsa::RecoveryId {
306 k256::ecdsa::RecoveryId::new(self.y_parity, false)
307 }
308
309 #[cfg(feature = "secp256k1")]
311 #[inline]
312 pub fn secp256k1_recid(&self) -> secp256k1::ecdsa::RecoveryId {
313 if self.y_parity {
314 secp256k1::ecdsa::RecoveryId::One
315 } else {
316 secp256k1::ecdsa::RecoveryId::Zero
317 }
318 }
319
320 #[cfg(any(feature = "k256", feature = "secp256k1"))]
323 #[inline]
324 pub fn recover_address_from_msg<T: AsRef<[u8]>>(
325 &self,
326 msg: T,
327 ) -> Result<Address, SignatureError> {
328 self.recover_address_from_prehash(&crate::eip191_hash_message(msg))
329 }
330
331 #[cfg(any(feature = "k256", feature = "secp256k1"))]
333 #[inline]
334 pub fn recover_address_from_prehash(&self, prehash: &B256) -> Result<Address, SignatureError> {
335 cfg_if::cfg_if! {
336 if #[cfg(feature = "secp256k1")] {
337 let pubkey = self.recover_from_prehash_secp256k1(prehash)?;
338 Ok(Address::from_raw_public_key(&pubkey.serialize_uncompressed()[1..]))
339 } else {
340 let vk = self.recover_from_prehash_k256(prehash)?;
341 Ok(Address::from_public_key(&vk))
342 }
343 }
344 }
345
346 #[cfg(feature = "k256")]
351 #[inline]
352 pub fn recover_from_msg<T: AsRef<[u8]>>(
353 &self,
354 msg: T,
355 ) -> Result<k256::ecdsa::VerifyingKey, SignatureError> {
356 self.recover_from_prehash(&crate::eip191_hash_message(msg))
357 }
358
359 #[cfg(feature = "k256")]
363 #[inline]
364 pub fn recover_from_prehash(
365 &self,
366 prehash: &B256,
367 ) -> Result<k256::ecdsa::VerifyingKey, SignatureError> {
368 self.recover_from_prehash_k256(prehash)
369 }
370
371 #[cfg(feature = "k256")]
375 #[inline]
376 fn recover_from_prehash_k256(
377 &self,
378 prehash: &B256,
379 ) -> Result<k256::ecdsa::VerifyingKey, SignatureError> {
380 let this = self.normalized_s();
381 k256::ecdsa::VerifyingKey::recover_from_prehash(
382 prehash.as_slice(),
383 &this.to_k256()?,
384 this.recid(),
385 )
386 .map_err(Into::into)
387 }
388
389 #[cfg(feature = "secp256k1")]
392 #[inline]
393 pub fn recover_from_msg_secp256k1<T: AsRef<[u8]>>(
394 &self,
395 msg: T,
396 ) -> Result<secp256k1::PublicKey, SignatureError> {
397 self.recover_from_prehash_secp256k1(&crate::eip191_hash_message(msg))
398 }
399
400 #[cfg(feature = "secp256k1")]
402 #[inline]
403 pub fn recover_from_prehash_secp256k1(
404 &self,
405 prehash: &B256,
406 ) -> Result<secp256k1::PublicKey, SignatureError> {
407 let this = self.normalized_s();
408 let sig = this.to_secp256k1()?;
409 let msg = secp256k1::Message::from_digest(prehash.0);
410 #[cfg(feature = "std")]
411 {
412 secp256k1::SECP256K1.recover_ecdsa(msg, &sig).map_err(Into::into)
413 }
414 #[cfg(not(feature = "std"))]
415 {
416 let secp = secp256k1::Secp256k1::verification_only();
417 secp.recover_ecdsa(msg, &sig).map_err(Into::into)
418 }
419 }
420
421 #[inline]
423 pub fn r(&self) -> U256 {
424 self.r
425 }
426
427 #[inline]
429 pub fn s(&self) -> U256 {
430 self.s
431 }
432
433 #[inline]
435 pub fn v(&self) -> bool {
436 self.y_parity
437 }
438
439 #[inline]
441 pub const fn v_byte(&self) -> u8 {
442 27 + self.y_parity as u8
443 }
444
445 #[cfg(feature = "rlp")]
447 pub fn rlp_rs_len(&self) -> usize {
448 alloy_rlp::Encodable::length(&self.r) + alloy_rlp::Encodable::length(&self.s)
449 }
450
451 #[cfg(feature = "rlp")]
453 pub fn write_rlp_rs(&self, out: &mut dyn alloy_rlp::BufMut) {
454 alloy_rlp::Encodable::encode(&self.r, out);
455 alloy_rlp::Encodable::encode(&self.s, out);
456 }
457
458 #[cfg(feature = "rlp")]
460 pub fn write_rlp_vrs(&self, out: &mut dyn alloy_rlp::BufMut, v: impl alloy_rlp::Encodable) {
461 v.encode(out);
462 self.write_rlp_rs(out);
463 }
464
465 #[doc(hidden)]
466 #[inline(always)]
467 pub fn test_signature() -> Self {
468 Self::from_scalars_and_parity(
469 b256!("0x840cfc572845f5786e702984c2a582528cad4b49b2a10b9db1be7fca90058565"),
470 b256!("0x25e7109ceb98168d95b09b18bbf6b685130e0562f233877d492b94eee0c5b6d1"),
471 false,
472 )
473 }
474}
475
476#[cfg(feature = "arbitrary")]
477impl<'a> arbitrary::Arbitrary<'a> for Signature {
478 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
479 Ok(Self::new(u.arbitrary()?, u.arbitrary()?, u.arbitrary()?))
480 }
481}
482
483#[cfg(feature = "arbitrary")]
484impl proptest::arbitrary::Arbitrary for Signature {
485 type Parameters = ();
486 type Strategy = proptest::strategy::Map<
487 <(U256, U256, bool) as proptest::arbitrary::Arbitrary>::Strategy,
488 fn((U256, U256, bool)) -> Self,
489 >;
490
491 fn arbitrary_with((): Self::Parameters) -> Self::Strategy {
492 use proptest::strategy::Strategy;
493 proptest::arbitrary::any::<(U256, U256, bool)>()
494 .prop_map(|(r, s, y_parity)| Self::new(r, s, y_parity))
495 }
496}
497
498#[cfg(feature = "serde")]
499mod signature_serde {
500 use super::Signature;
501 use crate::{U64, U256, normalize_v};
502 use serde::{Deserialize, Deserializer, Serialize};
503
504 #[derive(Serialize, Deserialize)]
505 struct HumanReadableRepr {
506 r: U256,
507 s: U256,
508 #[serde(rename = "yParity")]
509 y_parity: Option<U64>,
510 #[serde(default, skip_serializing_if = "Option::is_none")]
511 v: Option<U64>,
512 }
513
514 type NonHumanReadableRepr = (U256, U256, U64);
515
516 impl Serialize for Signature {
517 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
518 where
519 S: serde::Serializer,
520 {
521 if serializer.is_human_readable() {
523 HumanReadableRepr {
524 y_parity: Some(U64::from(self.y_parity as u64)),
525 v: Some(U64::from(self.y_parity as u64)),
526 r: self.r,
527 s: self.s,
528 }
529 .serialize(serializer)
530 } else {
531 let repr: NonHumanReadableRepr = (self.r, self.s, U64::from(self.y_parity as u64));
532 repr.serialize(serializer)
533 }
534 }
535 }
536
537 impl<'de> Deserialize<'de> for Signature {
538 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
539 where
540 D: Deserializer<'de>,
541 {
542 let (y_parity, v, r, s) = if deserializer.is_human_readable() {
543 let HumanReadableRepr { y_parity, v, r, s } = <_>::deserialize(deserializer)?;
544 (y_parity, v, r, s)
545 } else {
546 let (r, s, y_parity) = NonHumanReadableRepr::deserialize(deserializer)?;
547 (Some(y_parity), None, r, s)
548 };
549
550 let y_parity = if let Some(y_parity) = y_parity {
552 match y_parity.to::<u64>() {
553 0 => false,
554 1 => true,
555 _ => return Err(serde::de::Error::custom("invalid yParity")),
556 }
557 } else if let Some(v) = v {
558 normalize_v(v.to()).ok_or(serde::de::Error::custom("invalid v"))?
559 } else {
560 return Err(serde::de::Error::custom("missing `yParity` or `v`"));
561 };
562
563 Ok(Self::new(r, s, y_parity))
564 }
565 }
566}
567
568#[cfg(test)]
569mod tests {
570 use super::*;
571 use core::str::FromStr;
572
573 #[cfg(feature = "rlp")]
574 use alloy_rlp::{Decodable, Encodable};
575
576 #[test]
577 #[cfg(feature = "k256")]
578 #[cfg_attr(miri, ignore = "k256 is too slow under Miri")]
579 fn can_recover_tx_sender_not_normalized() {
580 let sig = Signature::from_str("48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c8041b").unwrap();
581 let hash = b256!("0x5eb4f5a33c621f32a8622d5f943b6b102994dfe4e5aebbefe69bb1b2aa0fc93e");
582 let expected = address!("0x0f65fe9276bc9a24ae7083ae28e2660ef72df99e");
583 assert_eq!(sig.recover_address_from_prehash(&hash).unwrap(), expected);
584 }
585
586 #[test]
587 #[cfg(feature = "k256")]
588 #[cfg_attr(miri, ignore = "k256 is too slow under Miri")]
589 fn recover_web3_signature() {
590 let sig = Signature::from_str(
593 "b91467e570a6466aa9e9876cbcd013baba02900b8979d43fe208a4a4f339f5fd6007e74cd82e037b800186422fc2da167c747ef045e5d18a5f5d4300f8e1a0291c"
594 ).expect("could not parse signature");
595 let expected = address!("0x2c7536E3605D9C16a7a3D7b1898e529396a65c23");
596 assert_eq!(sig.recover_address_from_msg("Some data").unwrap(), expected);
597 }
598
599 #[test]
600 fn signature_from_str() {
601 let s1 = Signature::from_str(
602 "0xaa231fbe0ed2b5418e6ba7c19bee2522852955ec50996c02a2fe3e71d30ddaf1645baf4823fea7cb4fcc7150842493847cfb6a6d63ab93e8ee928ee3f61f503500"
603 ).expect("could not parse 0x-prefixed signature");
604
605 let s2 = Signature::from_str(
606 "aa231fbe0ed2b5418e6ba7c19bee2522852955ec50996c02a2fe3e71d30ddaf1645baf4823fea7cb4fcc7150842493847cfb6a6d63ab93e8ee928ee3f61f503500"
607 ).expect("could not parse non-prefixed signature");
608
609 assert_eq!(s1, s2);
610 }
611
612 #[cfg(feature = "serde")]
613 #[test]
614 fn deserialize_with_parity() {
615 let raw_signature_with_y_parity = serde_json::json!({
616 "r": "0xc569c92f176a3be1a6352dd5005bfc751dcb32f57623dd2a23693e64bf4447b0",
617 "s": "0x1a891b566d369e79b7a66eecab1e008831e22daa15f91a0a0cf4f9f28f47ee05",
618 "v": "0x1",
619 "yParity": "0x1"
620 });
621
622 let signature: Signature = serde_json::from_value(raw_signature_with_y_parity).unwrap();
623
624 let expected = Signature::new(
625 U256::from_str("0xc569c92f176a3be1a6352dd5005bfc751dcb32f57623dd2a23693e64bf4447b0")
626 .unwrap(),
627 U256::from_str("0x1a891b566d369e79b7a66eecab1e008831e22daa15f91a0a0cf4f9f28f47ee05")
628 .unwrap(),
629 true,
630 );
631
632 assert_eq!(signature, expected);
633 }
634
635 #[cfg(feature = "serde")]
636 #[test]
637 fn serialize_both_parity() {
638 let signature = Signature::new(
640 U256::from_str("0xc569c92f176a3be1a6352dd5005bfc751dcb32f57623dd2a23693e64bf4447b0")
641 .unwrap(),
642 U256::from_str("0x1a891b566d369e79b7a66eecab1e008831e22daa15f91a0a0cf4f9f28f47ee05")
643 .unwrap(),
644 true,
645 );
646
647 let serialized = serde_json::to_string(&signature).unwrap();
648 assert_eq!(
649 serialized,
650 r#"{"r":"0xc569c92f176a3be1a6352dd5005bfc751dcb32f57623dd2a23693e64bf4447b0","s":"0x1a891b566d369e79b7a66eecab1e008831e22daa15f91a0a0cf4f9f28f47ee05","yParity":"0x1","v":"0x1"}"#
651 );
652 }
653
654 #[cfg(feature = "serde")]
655 #[test]
656 fn serialize_v_only() {
657 let signature = Signature::new(
659 U256::from_str("0xc569c92f176a3be1a6352dd5005bfc751dcb32f57623dd2a23693e64bf4447b0")
660 .unwrap(),
661 U256::from_str("0x1a891b566d369e79b7a66eecab1e008831e22daa15f91a0a0cf4f9f28f47ee05")
662 .unwrap(),
663 true,
664 );
665
666 let expected = r#"{"r":"0xc569c92f176a3be1a6352dd5005bfc751dcb32f57623dd2a23693e64bf4447b0","s":"0x1a891b566d369e79b7a66eecab1e008831e22daa15f91a0a0cf4f9f28f47ee05","yParity":"0x1","v":"0x1"}"#;
667
668 let serialized = serde_json::to_string(&signature).unwrap();
669 assert_eq!(serialized, expected);
670 }
671
672 #[cfg(feature = "serde")]
673 #[test]
674 fn bincode_roundtrip() {
675 let signature = Signature::new(
676 U256::from_str("0xc569c92f176a3be1a6352dd5005bfc751dcb32f57623dd2a23693e64bf4447b0")
677 .unwrap(),
678 U256::from_str("0x1a891b566d369e79b7a66eecab1e008831e22daa15f91a0a0cf4f9f28f47ee05")
679 .unwrap(),
680 true,
681 );
682
683 let bin = bincode::serialize(&signature).unwrap();
684 assert_eq!(bincode::deserialize::<Signature>(&bin).unwrap(), signature);
685 }
686
687 #[cfg(feature = "rlp")]
688 #[test]
689 fn signature_rlp_encode() {
690 let sig = Signature::from_str("48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c8041b").unwrap();
692
693 let mut buf = vec![];
695
696 sig.write_rlp_vrs(&mut buf, sig.v());
698
699 let expected = "80a048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804";
701
702 assert_eq!(hex::encode(&buf), expected);
704 }
705
706 #[cfg(feature = "rlp")]
707 #[test]
708 fn signature_rlp_length() {
709 let sig = Signature::from_str("48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c8041b").unwrap();
711
712 assert_eq!(sig.rlp_rs_len() + sig.v().length(), 67);
714 }
715
716 #[cfg(feature = "rlp")]
717 #[test]
718 fn rlp_vrs_len() {
719 let signature = Signature::test_signature();
720 assert_eq!(67, signature.rlp_rs_len() + 1);
721 }
722
723 #[cfg(feature = "rlp")]
724 #[test]
725 fn encode_and_decode() {
726 let signature = Signature::test_signature();
727
728 let mut encoded = Vec::new();
729 signature.write_rlp_vrs(&mut encoded, signature.v());
730 assert_eq!(encoded.len(), signature.rlp_rs_len() + signature.v().length());
731 let decoded = Signature::decode_rlp_vrs(&mut &*encoded, bool::decode).unwrap();
732 assert_eq!(signature, decoded);
733 }
734
735 #[test]
736 fn as_bytes() {
737 let signature = Signature::new(
738 U256::from_str(
739 "18515461264373351373200002665853028612451056578545711640558177340181847433846",
740 )
741 .unwrap(),
742 U256::from_str(
743 "46948507304638947509940763649030358759909902576025900602547168820602576006531",
744 )
745 .unwrap(),
746 false,
747 );
748
749 let expected = hex!(
750 "0x28ef61340bd939bc2195fe537567866003e1a15d3c71ff63e1590620aa63627667cbe9d8997f761aecb703304b3800ccf555c9f3dc64214b297fb1966a3b6d831b"
751 );
752 assert_eq!(signature.as_bytes(), expected);
753 }
754
755 #[test]
756 fn as_rsy() {
757 let signature = Signature::new(
758 U256::from_str(
759 "18515461264373351373200002665853028612451056578545711640558177340181847433846",
760 )
761 .unwrap(),
762 U256::from_str(
763 "46948507304638947509940763649030358759909902576025900602547168820602576006531",
764 )
765 .unwrap(),
766 false,
767 );
768
769 let expected = hex!(
770 "0x28ef61340bd939bc2195fe537567866003e1a15d3c71ff63e1590620aa63627667cbe9d8997f761aecb703304b3800ccf555c9f3dc64214b297fb1966a3b6d8300"
771 );
772 assert_eq!(signature.as_rsy(), expected);
773 }
774
775 #[test]
776 fn as_rsy_y_parity_true() {
777 let signature = Signature::new(
778 U256::from_str(
779 "18515461264373351373200002665853028612451056578545711640558177340181847433846",
780 )
781 .unwrap(),
782 U256::from_str(
783 "46948507304638947509940763649030358759909902576025900602547168820602576006531",
784 )
785 .unwrap(),
786 true,
787 );
788
789 let expected = hex!(
790 "0x28ef61340bd939bc2195fe537567866003e1a15d3c71ff63e1590620aa63627667cbe9d8997f761aecb703304b3800ccf555c9f3dc64214b297fb1966a3b6d8301"
791 );
792 assert_eq!(signature.as_rsy(), expected);
793 }
794
795 #[test]
796 fn v_byte() {
797 let signature = Signature::new(U256::ZERO, U256::ZERO, false);
798 assert_eq!(signature.v_byte(), 27);
799
800 let signature = signature.with_parity(true);
801 assert_eq!(signature.v_byte(), 28);
802 }
803
804 #[test]
805 fn as_erc2098_y_false() {
806 let signature = Signature::new(
807 U256::from_str(
808 "47323457007453657207889730243826965761922296599680473886588287015755652701072",
809 )
810 .unwrap(),
811 U256::from_str(
812 "57228803202727131502949358313456071280488184270258293674242124340113824882788",
813 )
814 .unwrap(),
815 false,
816 );
817
818 let expected = hex!(
819 "0x68a020a209d3d56c46f38cc50a33f704f4a9a10a59377f8dd762ac66910e9b907e865ad05c4035ab5792787d4a0297a43617ae897930a6fe4d822b8faea52064"
820 );
821 assert_eq!(signature.as_erc2098(), expected);
822 }
823
824 #[test]
825 fn as_erc2098_y_true() {
826 let signature = Signature::new(
827 U256::from_str("0x9328da16089fcba9bececa81663203989f2df5fe1faa6291a45381c81bd17f76")
828 .unwrap(),
829 U256::from_str("0x139c6d6b623b42da56557e5e734a43dc83345ddfadec52cbe24d0cc64f550793")
830 .unwrap(),
831 true,
832 );
833
834 let expected = hex!(
835 "0x9328da16089fcba9bececa81663203989f2df5fe1faa6291a45381c81bd17f76939c6d6b623b42da56557e5e734a43dc83345ddfadec52cbe24d0cc64f550793"
836 );
837 assert_eq!(signature.as_erc2098(), expected);
838 }
839
840 #[test]
841 fn from_erc2098_y_false() {
842 let expected = Signature::new(
843 U256::from_str(
844 "47323457007453657207889730243826965761922296599680473886588287015755652701072",
845 )
846 .unwrap(),
847 U256::from_str(
848 "57228803202727131502949358313456071280488184270258293674242124340113824882788",
849 )
850 .unwrap(),
851 false,
852 );
853
854 assert_eq!(
855 Signature::from_erc2098(&hex!(
856 "0x68a020a209d3d56c46f38cc50a33f704f4a9a10a59377f8dd762ac66910e9b907e865ad05c4035ab5792787d4a0297a43617ae897930a6fe4d822b8faea52064"
857 )),
858 expected
859 );
860 }
861
862 #[test]
863 fn from_erc2098_y_true() {
864 let expected = Signature::new(
865 U256::from_str("0x9328da16089fcba9bececa81663203989f2df5fe1faa6291a45381c81bd17f76")
866 .unwrap(),
867 U256::from_str("0x139c6d6b623b42da56557e5e734a43dc83345ddfadec52cbe24d0cc64f550793")
868 .unwrap(),
869 true,
870 );
871
872 assert_eq!(
873 Signature::from_erc2098(&hex!(
874 "0x9328da16089fcba9bececa81663203989f2df5fe1faa6291a45381c81bd17f76939c6d6b623b42da56557e5e734a43dc83345ddfadec52cbe24d0cc64f550793"
875 )),
876 expected
877 );
878 }
879
880 #[test]
881 fn display_impl() {
882 let sig = Signature::new(
883 U256::from_str("0x9328da16089fcba9bececa81663203989f2df5fe1faa6291a45381c81bd17f76")
884 .unwrap(),
885 U256::from_str("0x139c6d6b623b42da56557e5e734a43dc83345ddfadec52cbe24d0cc64f550793")
886 .unwrap(),
887 true,
888 );
889
890 assert_eq!(
891 format!("{sig}"),
892 "0x9328da16089fcba9bececa81663203989f2df5fe1faa6291a45381c81bd17f76139c6d6b623b42da56557e5e734a43dc83345ddfadec52cbe24d0cc64f5507931c"
893 );
894 }
895}