duniter_peer/
lib.rs

1//  Copyright (C) 2020  Éloïs SANCHEZ.
2//
3// This program is free software: you can redistribute it and/or modify
4// it under the terms of the GNU Affero General Public License as
5// published by the Free Software Foundation, either version 3 of the
6// License, or (at your option) any later version.
7//
8// This program is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11// GNU Affero General Public License for more details.
12//
13// You should have received a copy of the GNU Affero General Public License
14// along with this program.  If not, see <https://www.gnu.org/licenses/>.
15
16//! Define duniter peer card.
17
18#![deny(
19    clippy::expect_used,
20    clippy::unwrap_used,
21    missing_debug_implementations,
22    missing_copy_implementations,
23    trivial_casts,
24    trivial_numeric_casts,
25    unsafe_code,
26    unstable_features,
27    unused_import_braces
28)]
29
30pub(crate) use dubp_common::{
31    crypto::{
32        bases::b58::ToBase58,
33        keys::{
34            ed25519::{PublicKey, Signature},
35            PublicKey as _, Signature as _,
36        },
37    },
38    prelude::*,
39};
40pub(crate) use serde::{Deserialize, Serialize};
41pub(crate) use smallvec::SmallVec;
42
43#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
44pub struct PeerV10 {
45    pub currency: String,
46    pub pubkey: PublicKey,
47    pub blockstamp: Blockstamp,
48    pub endpoints: SmallVec<[String; 4]>,
49    pub signature: Signature,
50}
51
52impl PeerV10 {
53    pub fn to_raw_string(&self) -> String {
54        format!(
55            "{}{}\n",
56            self.to_raw_unsigned_string(),
57            self.signature.to_base64(),
58        )
59    }
60    fn to_raw_unsigned_string(&self) -> String {
61        format!(
62            "Version: 10\nType: Peer\nCurrency: {}\nPublicKey: {}\nBlock: {}\nEndpoints:\n{}\n",
63            self.currency,
64            self.pubkey.to_base58(),
65            self.blockstamp,
66            self.endpoints.join("\n"),
67        )
68    }
69    pub fn verify_sig(&self) -> Result<(), dubp_common::crypto::keys::SigError> {
70        self.pubkey
71            .verify(self.to_raw_unsigned_string().as_bytes(), &self.signature)
72    }
73}
74
75#[cfg(test)]
76mod tests {
77    use super::*;
78    use smallvec::smallvec;
79    use std::str::FromStr;
80    use unwrap::unwrap;
81
82    #[test]
83    fn test_peer_sig() {
84        let peer = PeerV10 {
85            currency: "g1".to_owned(),
86            pubkey: unwrap!(PublicKey::from_base58("8iVdpXqFLCxGyPqgVx5YbFSkmWKkceXveRd2yvBKeARL")),
87            blockstamp: unwrap!(Blockstamp::from_str("423354-00000033A87209DC21BD643088ED8AD52464A80C04BE3F8FBFA4291A9999BE50")),
88            endpoints: smallvec![
89                "BMAS g1.duniter.org 443".to_owned(),
90                "BASIC_MERKLED_API 91.121.157.13 10901".to_owned(),
91                "WS2P e66254bf g1.duniter.org 443 ws2p".to_owned()
92            ],
93            signature: unwrap!(Signature::from_base64("qr6Cnr/Qsgw/clbt0LbdkaFaUwhdgBJw5Fzpn8EhI9zM5/rGbVF6kqiB5pRJxf17XtI45qQ7H7SBbl8X2kAtCA==")),
94        };
95
96        let peer_raw = peer.to_raw_unsigned_string();
97        assert_eq!(
98            &peer_raw,
99            "Version: 10\nType: Peer\nCurrency: g1\nPublicKey: 8iVdpXqFLCxGyPqgVx5YbFSkmWKkceXveRd2yvBKeARL\nBlock: 423354-00000033A87209DC21BD643088ED8AD52464A80C04BE3F8FBFA4291A9999BE50\nEndpoints:\nBMAS g1.duniter.org 443\nBASIC_MERKLED_API 91.121.157.13 10901\nWS2P e66254bf g1.duniter.org 443 ws2p\n",
100        );
101        assert!(peer.verify_sig().is_ok());
102    }
103}