alloy_consensus/
encodable_signature.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
use alloy_primitives::{Parity, SignatureError, U256};

/// Helper trait used to streamline signatures encoding.
pub trait EncodableSignature: Sized {
    /// Instantiate from v, r, s.
    fn from_rs_and_parity<P: TryInto<Parity, Error = E>, E: Into<SignatureError>>(
        r: U256,
        s: U256,
        parity: P,
    ) -> Result<Self, SignatureError>;

    /// Returns the `r` component of this signature.
    fn r(&self) -> U256;

    /// Returns the `s` component of this signature.
    fn s(&self) -> U256;

    /// Returns the recovery ID as a `u8`.
    fn v(&self) -> Parity;

    /// Sets the recovery ID by normalizing a `v` value.
    fn with_parity<T: Into<Parity>>(self, parity: T) -> Self;

    /// Modifies the recovery ID by applying [EIP-155] to a `v` value.
    ///
    /// [EIP-155]: https://eips.ethereum.org/EIPS/eip-155
    #[inline]
    fn with_chain_id(self, chain_id: u64) -> Self
    where
        Self: Copy,
    {
        self.with_parity(self.v().with_chain_id(chain_id))
    }

    /// Modifies the recovery ID by dropping any [EIP-155] v value, converting
    /// to a simple parity bool.
    fn with_parity_bool(self) -> Self
    where
        Self: Copy,
    {
        self.with_parity(self.v().to_parity_bool())
    }

    /// Decode an RLP-encoded VRS signature.
    fn decode_rlp_vrs(buf: &mut &[u8]) -> Result<Self, alloy_rlp::Error> {
        use alloy_rlp::Decodable;

        let parity: Parity = Decodable::decode(buf)?;
        let r = Decodable::decode(buf)?;
        let s = Decodable::decode(buf)?;

        Self::from_rs_and_parity(r, s, parity)
            .map_err(|_| alloy_rlp::Error::Custom("attempted to decode invalid field element"))
    }

    /// Length of RLP RS field encoding
    fn rlp_rs_len(&self) -> usize {
        alloy_rlp::Encodable::length(&self.r()) + alloy_rlp::Encodable::length(&self.s())
    }

    /// Length of RLP V field encoding
    fn rlp_vrs_len(&self) -> usize {
        self.rlp_rs_len() + alloy_rlp::Encodable::length(&self.v())
    }

    /// Write R and S to an RLP buffer in progress.
    fn write_rlp_rs(&self, out: &mut dyn alloy_rlp::BufMut) {
        alloy_rlp::Encodable::encode(&self.r(), out);
        alloy_rlp::Encodable::encode(&self.s(), out);
    }

    /// Write the V to an RLP buffer without using EIP-155.
    fn write_rlp_v(&self, out: &mut dyn alloy_rlp::BufMut) {
        alloy_rlp::Encodable::encode(&self.v(), out);
    }

    /// Write the VRS to the output. The V will always be 27 or 28.
    fn write_rlp_vrs(&self, out: &mut dyn alloy_rlp::BufMut) {
        self.write_rlp_v(out);
        self.write_rlp_rs(out);
    }
}

impl EncodableSignature for alloy_primitives::Signature {
    fn from_rs_and_parity<P: TryInto<Parity, Error = E>, E: Into<SignatureError>>(
        r: U256,
        s: U256,
        parity: P,
    ) -> Result<Self, SignatureError> {
        Self::from_rs_and_parity(r, s, parity)
    }

    fn r(&self) -> U256 {
        self.r()
    }

    fn s(&self) -> U256 {
        self.s()
    }

    fn v(&self) -> Parity {
        self.v()
    }

    fn with_parity<T: Into<Parity>>(self, parity: T) -> Self {
        self.with_parity(parity)
    }
}