mithril_stm/bls_multi_signature/
signature.rs

1use crate::bls_multi_signature::helper::unsafe_helpers::{
2    p1_affine_to_sig, p2_affine_to_vk, sig_to_p1, vk_from_p2_affine,
3};
4use crate::bls_multi_signature::verification_key::VerificationKey;
5use crate::error::{blst_err_to_mithril, MultiSignatureError};
6use crate::stm::Index;
7use blake2::Blake2b;
8use blake2::{Blake2b512, Digest};
9use blst::min_sig::{AggregateSignature, PublicKey as BlstVk, Signature as BlstSig};
10use blst::{blst_p1, blst_p2, p1_affines, p2_affines};
11use digest::consts::U16;
12use std::cmp::Ordering;
13use std::iter::Sum;
14
15/// MultiSig signature, which is a wrapper over the `BlstSig` type.
16#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17pub struct Signature(pub BlstSig);
18
19impl Signature {
20    /// Verify a signature against a verification key.
21    pub fn verify(&self, msg: &[u8], mvk: &VerificationKey) -> Result<(), MultiSignatureError> {
22        blst_err_to_mithril(
23            self.0.validate(true).map_or_else(
24                |e| e,
25                |_| {
26                    self.0
27                        .verify(false, msg, &[], &[], &mvk.to_blst_vk(), false)
28                },
29            ),
30            Some(*self),
31            None,
32        )
33    }
34
35    /// Dense mapping function indexed by the index to be evaluated.
36    /// We hash the signature to produce a 64 bytes integer.
37    /// The return value of this function refers to
38    /// `ev = H("map" || msg || index || σ) <- MSP.Eval(msg,index,σ)` given in paper.
39    pub fn eval(&self, msg: &[u8], index: Index) -> [u8; 64] {
40        let hasher = Blake2b512::new()
41            .chain_update(b"map")
42            .chain_update(msg)
43            .chain_update(index.to_le_bytes())
44            .chain_update(self.to_bytes())
45            .finalize();
46
47        let mut output = [0u8; 64];
48        output.copy_from_slice(hasher.as_slice());
49
50        output
51    }
52
53    /// Convert an `Signature` to its compressed byte representation.
54    pub fn to_bytes(self) -> [u8; 48] {
55        self.0.to_bytes()
56    }
57
58    /// Convert a string of bytes into a `MspSig`.
59    ///
60    /// # Error
61    /// Returns an error if the byte string does not represent a point in the curve.
62    pub fn from_bytes(bytes: &[u8]) -> Result<Self, MultiSignatureError> {
63        match BlstSig::sig_validate(&bytes[..48], true) {
64            Ok(sig) => Ok(Self(sig)),
65            Err(e) => Err(blst_err_to_mithril(e, None, None)
66                .expect_err("If deserialization is not successful, blst returns and error different to SUCCESS."))
67        }
68    }
69
70    /// Compare two signatures. Used for PartialOrd impl, used to rank signatures. The comparison
71    /// function can be anything, as long as it is consistent across different nodes.
72    fn cmp_msp_sig(&self, other: &Self) -> Ordering {
73        let self_bytes = self.to_bytes();
74        let other_bytes = other.to_bytes();
75        let mut result = Ordering::Equal;
76
77        for (i, j) in self_bytes.iter().zip(other_bytes.iter()) {
78            result = i.cmp(j);
79            if result != Ordering::Equal {
80                return result;
81            }
82        }
83        result
84    }
85
86    /// Aggregate a slice of verification keys and Signatures by first hashing the
87    /// signatures into random scalars, and multiplying the signature and verification
88    /// key with the resulting value. This follows the steps defined in Figure 6,
89    /// `Aggregate` step.
90    pub fn aggregate(
91        vks: &[VerificationKey],
92        sigs: &[Signature],
93    ) -> Result<(VerificationKey, Signature), MultiSignatureError> {
94        if vks.len() != sigs.len() || vks.is_empty() {
95            return Err(MultiSignatureError::AggregateSignatureInvalid);
96        }
97
98        if vks.len() < 2 {
99            return Ok((vks[0], sigs[0]));
100        }
101
102        let mut hashed_sigs = Blake2b::<U16>::new();
103        for sig in sigs {
104            hashed_sigs.update(sig.to_bytes());
105        }
106
107        // First we generate the scalars
108        let mut scalars = Vec::with_capacity(vks.len() * 128);
109        let mut signatures = Vec::with_capacity(vks.len());
110        for (index, sig) in sigs.iter().enumerate() {
111            let mut hasher = hashed_sigs.clone();
112            hasher.update(index.to_be_bytes());
113            signatures.push(sig.0);
114            scalars.extend_from_slice(hasher.finalize().as_slice());
115        }
116
117        let transmuted_vks: Vec<blst_p2> = vks.iter().map(vk_from_p2_affine).collect();
118        let transmuted_sigs: Vec<blst_p1> = signatures.iter().map(sig_to_p1).collect();
119
120        let grouped_vks = p2_affines::from(transmuted_vks.as_slice());
121        let grouped_sigs = p1_affines::from(transmuted_sigs.as_slice());
122
123        let aggr_vk: BlstVk = p2_affine_to_vk(&grouped_vks.mult(&scalars, 128));
124        let aggr_sig: BlstSig = p1_affine_to_sig(&grouped_sigs.mult(&scalars, 128));
125
126        Ok((VerificationKey(aggr_vk), Signature(aggr_sig)))
127    }
128
129    /// Verify a set of signatures with their corresponding verification keys using the
130    /// aggregation mechanism of Figure 6.
131    pub fn verify_aggregate(
132        msg: &[u8],
133        vks: &[VerificationKey],
134        sigs: &[Signature],
135    ) -> Result<(), MultiSignatureError> {
136        let (aggr_vk, aggr_sig) = Self::aggregate(vks, sigs)?;
137
138        blst_err_to_mithril(
139            aggr_sig
140                .0
141                .verify(false, msg, &[], &[], &aggr_vk.to_blst_vk(), false),
142            Some(aggr_sig),
143            None,
144        )
145    }
146
147    /// Batch verify several sets of signatures with their corresponding verification keys.
148    #[cfg(feature = "batch-verify-aggregates")]
149    pub fn batch_verify_aggregates(
150        msgs: &[Vec<u8>],
151        vks: &[VerificationKey],
152        sigs: &[Signature],
153    ) -> Result<(), MultiSignatureError> {
154        let batched_sig: BlstSig = match AggregateSignature::aggregate(
155            &(sigs.iter().map(|sig| &sig.0).collect::<Vec<&BlstSig>>()),
156            false,
157        ) {
158            Ok(sig) => BlstSig::from_aggregate(&sig),
159            Err(e) => return blst_err_to_mithril(e, None, None),
160        };
161
162        let p2_vks: Vec<BlstVk> = vks.iter().map(|vk| vk.to_blst_vk()).collect();
163        let p2_vks_ref: Vec<&BlstVk> = p2_vks.iter().collect();
164        let slice_msgs = msgs
165            .iter()
166            .map(|msg| msg.as_slice())
167            .collect::<Vec<&[u8]>>();
168
169        blst_err_to_mithril(
170            batched_sig.aggregate_verify(false, &slice_msgs, &[], &p2_vks_ref, false),
171            None,
172            None,
173        )
174        .map_err(|_| MultiSignatureError::BatchInvalid)
175    }
176}
177
178impl<'a> Sum<&'a Self> for Signature {
179    fn sum<I>(iter: I) -> Self
180    where
181        I: Iterator<Item = &'a Self>,
182    {
183        let signatures: Vec<&BlstSig> = iter.map(|x| &x.0).collect();
184        assert!(!signatures.is_empty(), "One cannot add an empty vector");
185        let aggregate = AggregateSignature::aggregate(&signatures, false)
186            .expect("An MspSig is always a valid signature. This function only fails if signatures is empty or if the signatures are invalid, none of which can happen.")
187            .to_signature();
188
189        Self(aggregate)
190    }
191}
192
193impl PartialOrd for Signature {
194    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
195        Some(std::cmp::Ord::cmp(self, other))
196    }
197}
198
199impl Ord for Signature {
200    fn cmp(&self, other: &Self) -> Ordering {
201        self.cmp_msp_sig(other)
202    }
203}