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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
use assert_fs::fixture::{ChildPath, PathChild};
use chain_crypto::bech32::Bech32;
use chain_vote::{
    committee::MemberCommunicationPublicKey, tally::OpeningVoteKey, MemberCommunicationKey,
    MemberPublicKey,
};
use jormungandr_lib::interfaces::CommitteeIdDef;
use std::{fmt, fs::File, io::Write};
#[derive(Clone)]
pub struct CommitteeCommunicationData {
    pub id: CommitteeIdDef,
    pub communication_public_key: MemberCommunicationPublicKey,
    communication_secret_key: Option<MemberCommunicationKey>,
}

impl CommitteeCommunicationData {
    pub fn write_to(&self, directory: &ChildPath) {
        std::fs::create_dir_all(directory.path()).unwrap();
        write_to(
            self.communication_public_key.to_bech32_str(),
            directory,
            "communication.pk",
        );
        if let Some(private) = &self.communication_secret_key {
            write_to(private.to_bech32_str(), directory, "communication.sk");
        }
    }

    pub fn public(
        id: CommitteeIdDef,
        communication_public_key: MemberCommunicationPublicKey,
    ) -> Self {
        Self {
            id,
            communication_public_key,
            communication_secret_key: None,
        }
    }

    pub fn private(id: CommitteeIdDef, private: MemberCommunicationKey) -> Self {
        let communication_public_key = private.to_public();
        Self {
            id,
            communication_public_key,
            communication_secret_key: Some(private),
        }
    }
}

#[derive(Clone)]
pub struct CommitteeMembershipData {
    pub id: CommitteeIdDef,
    pub member_public_key: MemberPublicKey,
    member_secret_key: Option<OpeningVoteKey>,
}

impl CommitteeMembershipData {
    pub(crate) fn member_secret_key(&self) -> Result<OpeningVoteKey, Error> {
        self.member_secret_key
            .clone()
            .ok_or(Error::NoMemberSecretKeyDefined)
    }
}

impl fmt::Debug for CommitteeMembershipData {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("CommitteeMembershipData")?;
        if let Some(member_secret_key) = &self.member_secret_key {
            write!(
                f,
                "member secret key: {}",
                member_secret_key.to_bech32_str()
            )?;
        }
        write!(
            f,
            "member public key: {}",
            self.member_public_key.to_bech32_str()
        )?;
        f.write_str(")")
    }
}

#[derive(thiserror::Error, Debug)]
pub enum Error {
    #[error("no secret key defined")]
    NoMemberSecretKeyDefined,
}

impl CommitteeMembershipData {
    pub fn write_to(&self, directory: &ChildPath) {
        std::fs::create_dir_all(directory.path()).unwrap();
        write_to(
            self.member_public_key.to_bech32_str(),
            directory,
            "member.pk",
        );
        if let Some(private) = &self.member_secret_key {
            write_to(private.to_bech32_str(), directory, "member.sk");
        }
    }

    pub fn public(id: CommitteeIdDef, member_public_key: MemberPublicKey) -> Self {
        Self {
            id,
            member_public_key,
            member_secret_key: None,
        }
    }

    pub fn private(id: CommitteeIdDef, private: OpeningVoteKey) -> Self {
        let member_public_key = private.to_public();
        Self {
            id,
            member_public_key,
            member_secret_key: Some(private),
        }
    }
}

impl fmt::Debug for CommitteeCommunicationData {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("CommitteeCommunicationData")?;
        if let Some(communication_secret_key) = &self.communication_secret_key {
            write!(
                f,
                "communication secret key: {}",
                communication_secret_key.to_bech32_str()
            )?;
        }
        write!(
            f,
            "communication public key: {}",
            self.communication_public_key.to_bech32_str()
        )?;
        f.write_str(")")
    }
}

pub fn write_to(key: String, directory: &ChildPath, name: &str) {
    let path = directory.child(name);
    let mut file = File::create(path.path()).unwrap();
    writeln!(file, "{}", key).unwrap()
}