mithril_stm/protocol/single_signature/
signature.rs

1use std::{
2    cmp::Ordering,
3    hash::{Hash, Hasher},
4};
5
6use anyhow::{Context, anyhow};
7use blake2::digest::{Digest, FixedOutput};
8use serde::{Deserialize, Serialize};
9
10use crate::{
11    AggregateVerificationKey, Index, Parameters, SignatureError, Stake, StmResult, VerificationKey,
12    is_lottery_won, signature_scheme::BlsSignature,
13};
14
15/// Signature created by a single party who has won the lottery.
16#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct SingleSignature {
18    /// The signature from the underlying MSP scheme.
19    pub sigma: BlsSignature,
20    /// The index(es) for which the signature is valid
21    pub indexes: Vec<Index>,
22    /// Merkle tree index of the signer.
23    pub signer_index: Index,
24}
25
26impl SingleSignature {
27    /// Verify an stm signature by checking that the lottery was won, the merkle path is correct,
28    /// the indexes are in the desired range and the underlying multi signature validates.
29    pub fn verify<D: Clone + Digest + FixedOutput>(
30        &self,
31        params: &Parameters,
32        pk: &VerificationKey,
33        stake: &Stake,
34        avk: &AggregateVerificationKey<D>,
35        msg: &[u8],
36    ) -> StmResult<()> {
37        let msgp = avk.get_merkle_tree_batch_commitment().concatenate_with_message(msg);
38        self.basic_verify(params, pk, stake, &msgp, &avk.get_total_stake())
39            .with_context(|| {
40                format!(
41                    "Single signature verification failed for signer index {}.",
42                    self.signer_index
43                )
44            })?;
45        Ok(())
46    }
47
48    /// Verify that all indices of a signature are valid.
49    pub(crate) fn check_indices(
50        &self,
51        params: &Parameters,
52        stake: &Stake,
53        msg: &[u8],
54        total_stake: &Stake,
55    ) -> StmResult<()> {
56        for &index in &self.indexes {
57            if index > params.m {
58                return Err(anyhow!(SignatureError::IndexBoundFailed(index, params.m)));
59            }
60
61            let ev = self.sigma.evaluate_dense_mapping(msg, index);
62
63            if !is_lottery_won(params.phi_f, ev, *stake, *total_stake) {
64                return Err(anyhow!(SignatureError::LotteryLost));
65            }
66        }
67
68        Ok(())
69    }
70
71    /// Convert an `SingleSignature` into bytes
72    ///
73    /// # Layout
74    /// * Stake
75    /// * Number of valid indexes (as u64)
76    /// * Indexes of the signature
77    /// * Public Key
78    /// * Signature
79    /// * Merkle index of the signer.
80    pub fn to_bytes(&self) -> Vec<u8> {
81        let mut output = Vec::new();
82        output.extend_from_slice(&(self.indexes.len() as u64).to_be_bytes());
83
84        for index in &self.indexes {
85            output.extend_from_slice(&index.to_be_bytes());
86        }
87
88        output.extend_from_slice(&self.sigma.to_bytes());
89
90        output.extend_from_slice(&self.signer_index.to_be_bytes());
91        output
92    }
93
94    /// Extract a batch compatible `SingleSignature` from a byte slice.
95    pub fn from_bytes<D: Clone + Digest + FixedOutput>(bytes: &[u8]) -> StmResult<SingleSignature> {
96        let mut u64_bytes = [0u8; 8];
97
98        u64_bytes.copy_from_slice(bytes.get(0..8).ok_or(SignatureError::SerializationError)?);
99        let nr_indexes = u64::from_be_bytes(u64_bytes) as usize;
100
101        let mut indexes = Vec::new();
102        for i in 0..nr_indexes {
103            u64_bytes.copy_from_slice(
104                bytes
105                    .get(8 + i * 8..16 + i * 8)
106                    .ok_or(SignatureError::SerializationError)?,
107            );
108            indexes.push(u64::from_be_bytes(u64_bytes));
109        }
110
111        let offset = 8 + nr_indexes * 8;
112        let sigma = BlsSignature::from_bytes(
113            bytes
114                .get(offset..offset + 48)
115                .ok_or(SignatureError::SerializationError)?,
116        )?;
117
118        u64_bytes.copy_from_slice(
119            bytes
120                .get(offset + 48..offset + 56)
121                .ok_or(SignatureError::SerializationError)?,
122        );
123        let signer_index = u64::from_be_bytes(u64_bytes);
124
125        Ok(SingleSignature {
126            sigma,
127            indexes,
128            signer_index,
129        })
130    }
131
132    /// Compare two `SingleSignature` by their signers' merkle tree indexes.
133    fn compare_signer_index(&self, other: &Self) -> Ordering {
134        self.signer_index.cmp(&other.signer_index)
135    }
136
137    /// Compare two `SingleSignature` by their signers' merkle tree indexes.
138    #[deprecated(since = "0.5.0", note = "This function will be removed")]
139    pub fn cmp_stm_sig(&self, other: &Self) -> Ordering {
140        Self::compare_signer_index(self, other)
141    }
142
143    /// Verify a basic signature by checking that the lottery was won,
144    /// the indexes are in the desired range and the underlying multi signature validates.
145    pub(crate) fn basic_verify(
146        &self,
147        params: &Parameters,
148        pk: &VerificationKey,
149        stake: &Stake,
150        msg: &[u8],
151        total_stake: &Stake,
152    ) -> StmResult<()> {
153        self.sigma
154            .verify(msg, pk)
155            .with_context(|| "Basic verification of single signature failed.")?;
156        self.check_indices(params, stake, msg, total_stake)
157            .with_context(|| "Basic verification of single signature failed.")?;
158
159        Ok(())
160    }
161
162    /// Will be deprecated. Use `basic_verify` instead.
163    #[deprecated(since = "0.5.0", note = "Use `basic_verify` instead")]
164    pub fn core_verify(
165        &self,
166        params: &Parameters,
167        pk: &VerificationKey,
168        stake: &Stake,
169        msg: &[u8],
170        total_stake: &Stake,
171    ) -> StmResult<()> {
172        Self::basic_verify(self, params, pk, stake, msg, total_stake)
173    }
174}
175
176impl Hash for SingleSignature {
177    fn hash<H: Hasher>(&self, state: &mut H) {
178        Hash::hash_slice(&self.sigma.to_bytes(), state)
179    }
180}
181
182impl PartialEq for SingleSignature {
183    fn eq(&self, other: &Self) -> bool {
184        self.sigma == other.sigma
185    }
186}
187
188impl Eq for SingleSignature {}
189
190impl PartialOrd for SingleSignature {
191    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
192        Some(std::cmp::Ord::cmp(self, other))
193    }
194}
195
196impl Ord for SingleSignature {
197    fn cmp(&self, other: &Self) -> Ordering {
198        self.signer_index.cmp(&other.signer_index)
199    }
200}
201
202#[cfg(test)]
203mod tests {
204    mod golden {
205        use blake2::{Blake2b, digest::consts::U32};
206        use rand_chacha::ChaCha20Rng;
207        use rand_core::SeedableRng;
208
209        use crate::{
210            ClosedKeyRegistration, KeyRegistration, Parameters, Signer, SingleSignature,
211            signature_scheme::{BlsSigningKey, BlsVerificationKeyProofOfPossession},
212        };
213
214        type D = Blake2b<U32>;
215
216        const GOLDEN_JSON: &str = r#"
217        {
218            "sigma": [
219                149, 157, 201, 187, 140, 54, 0, 128, 209, 88, 16, 203, 61, 78, 77, 98, 161,
220                133, 58, 152, 29, 74, 217, 113, 64, 100, 10, 161, 186, 167, 133, 114, 211,
221                153, 218, 56, 223, 84, 105, 242, 41, 54, 224, 170, 208, 185, 126, 83
222            ],
223            "indexes": [1, 4, 5, 8],
224            "signer_index": 1
225        }"#;
226
227        fn golden_value() -> SingleSignature {
228            let mut rng = ChaCha20Rng::from_seed([0u8; 32]);
229            let msg = [0u8; 16];
230            let params = Parameters {
231                m: 10,
232                k: 5,
233                phi_f: 0.8,
234            };
235            let sk_1 = BlsSigningKey::generate(&mut rng);
236            let sk_2 = BlsSigningKey::generate(&mut rng);
237            let pk_1 = BlsVerificationKeyProofOfPossession::from(&sk_1);
238            let pk_2 = BlsVerificationKeyProofOfPossession::from(&sk_2);
239            let mut key_reg = KeyRegistration::init();
240            key_reg.register(1, pk_1).unwrap();
241            key_reg.register(1, pk_2).unwrap();
242            let closed_key_reg: ClosedKeyRegistration<D> = key_reg.close();
243            let signer = Signer::set_signer(1, 1, params, sk_1, pk_1.vk, closed_key_reg);
244            signer.sign(&msg).unwrap()
245        }
246
247        #[test]
248        fn golden_conversions() {
249            let value = serde_json::from_str(GOLDEN_JSON)
250                .expect("This JSON deserialization should not fail");
251            assert_eq!(golden_value(), value);
252
253            let serialized =
254                serde_json::to_string(&value).expect("This JSON serialization should not fail");
255            let golden_serialized = serde_json::to_string(&golden_value())
256                .expect("This JSON serialization should not fail");
257            assert_eq!(golden_serialized, serialized);
258        }
259    }
260}