iq_cometbft/
bytes.rs

1//! Signing arbitrary bytes.
2
3use crate::{prelude::*, privval::RemoteSignerError};
4
5/// A request to sign arbitrary application-specific bytes (e.g. consensus metadata, hashes).
6#[derive(Clone, PartialEq, Eq, Debug)]
7pub struct SignBytesRequest {
8    /// Bytes to sign
9    pub bytes: Vec<u8>,
10}
11
12/// Response to a `SignBytesRequest`, containing a signature if successful or an error otherwise.
13#[derive(Clone, PartialEq, Eq, Debug)]
14pub struct SignBytesResponse {
15    /// Signature
16    pub signature: Vec<u8>,
17    /// Response error
18    pub error: Option<RemoteSignerError>,
19}
20
21// =============================================================================
22// Protobuf conversions
23// =============================================================================
24
25mod v1 {
26    use super::{SignBytesRequest, SignBytesResponse};
27    use crate::{prelude::*, Error};
28    use cometbft_proto::privval::v1::{
29        SignBytesRequest as RawSignBytesRequest, SignBytesResponse as RawSignBytesResponse,
30    };
31    use cometbft_proto::Protobuf;
32
33    impl Protobuf<RawSignBytesRequest> for SignBytesRequest {}
34    impl Protobuf<RawSignBytesResponse> for SignBytesResponse {}
35
36    impl From<RawSignBytesRequest> for SignBytesRequest {
37        fn from(req: RawSignBytesRequest) -> Self {
38            SignBytesRequest { bytes: req.value }
39        }
40    }
41
42    impl From<SignBytesRequest> for RawSignBytesRequest {
43        fn from(req: SignBytesRequest) -> Self {
44            RawSignBytesRequest { value: req.bytes }
45        }
46    }
47
48    impl TryFrom<RawSignBytesResponse> for SignBytesResponse {
49        type Error = Error;
50
51        fn try_from(resp: RawSignBytesResponse) -> Result<Self, Self::Error> {
52            Ok(SignBytesResponse {
53                signature: resp.signature,
54                error: resp.error.map(TryInto::try_into).transpose()?,
55            })
56        }
57    }
58
59    impl From<SignBytesResponse> for RawSignBytesResponse {
60        fn from(resp: SignBytesResponse) -> Self {
61            RawSignBytesResponse {
62                signature: resp.signature,
63                error: resp.error.map(Into::into),
64            }
65        }
66    }
67}
68
69#[cfg(test)]
70mod tests {
71    use super::{SignBytesRequest, SignBytesResponse};
72
73    mod v1 {
74        use super::*;
75        use crate::privval::RemoteSignerError;
76        use cometbft_proto::privval::v1::{
77            SignBytesRequest as RawSignBytesRequest, SignBytesResponse as RawSignBytesResponse,
78        };
79
80        #[test]
81        fn test_protobuf_conversion_request_round_trip() {
82            let original = SignBytesRequest {
83                bytes: b"test bytes".to_vec(),
84            };
85            let raw: RawSignBytesRequest = original.clone().into();
86            let decoded = SignBytesRequest::from(raw);
87            assert_eq!(original, decoded);
88        }
89
90        #[test]
91        fn test_protobuf_conversion_response_with_signature() {
92            let original = SignBytesResponse {
93                signature: b"test signature".to_vec(),
94                error: None,
95            };
96            let raw: RawSignBytesResponse = original.clone().into();
97            let decoded = SignBytesResponse::try_from(raw).unwrap();
98            assert_eq!(original, decoded);
99        }
100
101        #[test]
102        fn test_protobuf_conversion_response_with_error() {
103            let original = SignBytesResponse {
104                signature: b"test signature".to_vec(),
105                error: Some(RemoteSignerError {
106                    code: 0,
107                    description: "test".into(),
108                }),
109            };
110            let raw: RawSignBytesResponse = original.clone().into();
111            let decoded = SignBytesResponse::try_from(raw).unwrap();
112            assert_eq!(original, decoded);
113        }
114    }
115}