iota_types/
message_envelope.rs

1// Copyright (c) Mysten Labs, Inc.
2// Modifications Copyright (c) 2024 IOTA Stiftung
3// SPDX-License-Identifier: Apache-2.0
4
5use std::{
6    fmt::{Debug, Display, Formatter},
7    ops::{Deref, DerefMut},
8};
9
10use fastcrypto::traits::KeyPair;
11use once_cell::sync::OnceCell;
12use serde::{Deserialize, Serialize, de::DeserializeOwned};
13use serde_name::{DeserializeNameAdapter, SerializeNameAdapter};
14use shared_crypto::intent::{Intent, IntentScope};
15
16use crate::{
17    base_types::AuthorityName,
18    committee::{Committee, EpochId},
19    crypto::{
20        AuthorityKeyPair, AuthorityQuorumSignInfo, AuthoritySignInfo, AuthoritySignInfoTrait,
21        AuthoritySignature, AuthorityStrongQuorumSignInfo, EmptySignInfo, Signer,
22    },
23    error::IotaResult,
24    executable_transaction::CertificateProof,
25    messages_checkpoint::CheckpointSequenceNumber,
26    transaction::SenderSignedData,
27};
28
29pub trait Message {
30    type DigestType: Clone + Debug;
31    const SCOPE: IntentScope;
32
33    fn scope(&self) -> IntentScope {
34        Self::SCOPE
35    }
36
37    fn digest(&self) -> Self::DigestType;
38}
39
40#[derive(Clone, Debug, Eq, Serialize, Deserialize)]
41#[serde(remote = "Envelope")]
42pub struct Envelope<T: Message, S> {
43    #[serde(skip)]
44    digest: OnceCell<T::DigestType>,
45
46    data: T,
47    auth_signature: S,
48}
49
50impl<'de, T, S> Deserialize<'de> for Envelope<T, S>
51where
52    T: Message + Deserialize<'de>,
53    S: Deserialize<'de>,
54{
55    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
56    where
57        D: serde::de::Deserializer<'de>,
58    {
59        Envelope::deserialize(DeserializeNameAdapter::new(
60            deserializer,
61            std::any::type_name::<Self>(),
62        ))
63    }
64}
65
66impl<T, Sig> Serialize for Envelope<T, Sig>
67where
68    T: Message + Serialize,
69    Sig: Serialize,
70{
71    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
72    where
73        S: serde::ser::Serializer,
74    {
75        Envelope::serialize(
76            self,
77            SerializeNameAdapter::new(serializer, std::any::type_name::<Self>()),
78        )
79    }
80}
81
82impl<T: Message, S> Envelope<T, S> {
83    pub fn new_from_data_and_sig(data: T, sig: S) -> Self {
84        Self {
85            digest: Default::default(),
86            data,
87            auth_signature: sig,
88        }
89    }
90
91    pub fn data(&self) -> &T {
92        &self.data
93    }
94
95    pub fn into_data(self) -> T {
96        self.data
97    }
98
99    pub fn into_sig(self) -> S {
100        self.auth_signature
101    }
102
103    pub fn into_data_and_sig(self) -> (T, S) {
104        let Self {
105            data,
106            auth_signature,
107            ..
108        } = self;
109        (data, auth_signature)
110    }
111
112    /// Remove the authority signatures `S` from this envelope.
113    pub fn into_unsigned(self) -> Envelope<T, EmptySignInfo> {
114        Envelope::<T, EmptySignInfo>::new(self.into_data())
115    }
116
117    pub fn auth_sig(&self) -> &S {
118        &self.auth_signature
119    }
120
121    pub fn auth_sig_mut_for_testing(&mut self) -> &mut S {
122        &mut self.auth_signature
123    }
124
125    pub fn digest(&self) -> &T::DigestType {
126        self.digest.get_or_init(|| self.data.digest())
127    }
128
129    pub fn data_mut_for_testing(&mut self) -> &mut T {
130        &mut self.data
131    }
132}
133
134impl<T: Message + PartialEq, S: PartialEq> PartialEq for Envelope<T, S> {
135    fn eq(&self, other: &Self) -> bool {
136        self.data == other.data && self.auth_signature == other.auth_signature
137    }
138}
139
140impl<T: Message> Envelope<T, EmptySignInfo> {
141    pub fn new(data: T) -> Self {
142        Self {
143            digest: OnceCell::new(),
144            data,
145            auth_signature: EmptySignInfo {},
146        }
147    }
148}
149
150impl<T> Envelope<T, AuthoritySignInfo>
151where
152    T: Message + Serialize,
153{
154    pub fn new(
155        epoch: EpochId,
156        data: T,
157        secret: &dyn Signer<AuthoritySignature>,
158        authority: AuthorityName,
159    ) -> Self {
160        let auth_signature = Self::sign(epoch, &data, secret, authority);
161        Self {
162            digest: OnceCell::new(),
163            data,
164            auth_signature,
165        }
166    }
167
168    pub fn sign(
169        epoch: EpochId,
170        data: &T,
171        secret: &dyn Signer<AuthoritySignature>,
172        authority: AuthorityName,
173    ) -> AuthoritySignInfo {
174        AuthoritySignInfo::new(epoch, &data, Intent::iota_app(T::SCOPE), authority, secret)
175    }
176
177    pub fn epoch(&self) -> EpochId {
178        self.auth_signature.epoch
179    }
180}
181
182impl Envelope<SenderSignedData, AuthoritySignInfo> {
183    pub fn verify_committee_sigs_only(&self, committee: &Committee) -> IotaResult {
184        self.auth_signature.verify_secure(
185            self.data(),
186            Intent::iota_app(IntentScope::SenderSignedTransaction),
187            committee,
188        )
189    }
190}
191
192impl<T, const S: bool> Envelope<T, AuthorityQuorumSignInfo<S>>
193where
194    T: Message + Serialize,
195{
196    pub fn new(
197        data: T,
198        signatures: Vec<AuthoritySignInfo>,
199        committee: &Committee,
200    ) -> IotaResult<Self> {
201        let cert = Self {
202            digest: OnceCell::new(),
203            data,
204            auth_signature: AuthorityQuorumSignInfo::<S>::new_from_auth_sign_infos(
205                signatures, committee,
206            )?,
207        };
208
209        Ok(cert)
210    }
211
212    pub fn new_from_keypairs_for_testing(
213        data: T,
214        keypairs: &[AuthorityKeyPair],
215        committee: &Committee,
216    ) -> Self {
217        let signatures = keypairs
218            .iter()
219            .map(|keypair| {
220                AuthoritySignInfo::new(
221                    committee.epoch(),
222                    &data,
223                    Intent::iota_app(T::SCOPE),
224                    keypair.public().into(),
225                    keypair,
226                )
227            })
228            .collect();
229        Self::new(data, signatures, committee).unwrap()
230    }
231
232    pub fn epoch(&self) -> EpochId {
233        self.auth_signature.epoch
234    }
235}
236
237/// TrustedEnvelope is a serializable wrapper around Envelope which is
238/// `Into<VerifiedEnvelope>` - in other words it models a verified message which
239/// has been written to the db (or some other trusted store), and may be read
240/// back from the db without further signature verification.
241///
242/// TrustedEnvelope should *only* appear in database interfaces.
243///
244/// DO NOT USE in networked APIs.
245///
246/// Because it is used very sparingly, it can be audited easily: Use
247/// rust-analyzer, or run: git grep -E 'TrustedEnvelope'
248///
249/// And verify that none of the uses appear in any network APIs.
250#[derive(Clone, Serialize, Deserialize)]
251pub struct TrustedEnvelope<T: Message, S>(Envelope<T, S>);
252
253impl<T, S: Debug> Debug for TrustedEnvelope<T, S>
254where
255    T: Message + Debug,
256{
257    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
258        write!(f, "{:?}", self.0)
259    }
260}
261
262impl<T: Message, S> TrustedEnvelope<T, S> {
263    pub fn into_inner(self) -> Envelope<T, S> {
264        self.0
265    }
266
267    pub fn inner(&self) -> &Envelope<T, S> {
268        &self.0
269    }
270}
271
272// An empty marker struct that can't be serialized.
273#[derive(Clone)]
274struct NoSer;
275// Never remove this assert!
276static_assertions::assert_not_impl_any!(NoSer: Serialize, DeserializeOwned);
277
278#[derive(Clone)]
279pub struct VerifiedEnvelope<T: Message, S>(TrustedEnvelope<T, S>, NoSer);
280
281impl<T, S: Debug> Debug for VerifiedEnvelope<T, S>
282where
283    T: Message + Debug,
284{
285    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
286        write!(f, "{:?}", self.0.0)
287    }
288}
289
290impl<T: Message, S> VerifiedEnvelope<T, S> {
291    /// This API should only be called when the input is already verified.
292    pub fn new_from_verified(inner: Envelope<T, S>) -> Self {
293        Self(TrustedEnvelope(inner), NoSer)
294    }
295
296    /// There are some situations (e.g. fragment verification) where its very
297    /// awkward and/or inefficient to obtain verified certificates from
298    /// calling CertifiedTransaction::verify() Use this carefully.
299    pub fn new_unchecked(inner: Envelope<T, S>) -> Self {
300        Self(TrustedEnvelope(inner), NoSer)
301    }
302
303    pub fn into_inner(self) -> Envelope<T, S> {
304        self.0.0
305    }
306
307    pub fn inner(&self) -> &Envelope<T, S> {
308        &self.0.0
309    }
310
311    pub fn into_message(self) -> T {
312        self.into_inner().into_data()
313    }
314
315    /// Use this when you need to serialize a verified envelope.
316    /// This should generally only be used for database writes.
317    /// ***never use over the network!***
318    pub fn serializable_ref(&self) -> &TrustedEnvelope<T, S> {
319        &self.0
320    }
321
322    /// Use this when you need to serialize a verified envelope.
323    /// This should generally only be used for database writes.
324    /// ***never use over the network!***
325    pub fn serializable(self) -> TrustedEnvelope<T, S> {
326        self.0
327    }
328
329    /// Remove the authority signatures `S` from this envelope.
330    pub fn into_unsigned(self) -> VerifiedEnvelope<T, EmptySignInfo> {
331        VerifiedEnvelope::<T, EmptySignInfo>::new_from_verified(self.into_inner().into_unsigned())
332    }
333}
334
335/// After deserialization, a TrustedTransactionEnvelope can be turned back into
336/// a VerifiedTransactionEnvelope.
337impl<T: Message, S> From<TrustedEnvelope<T, S>> for VerifiedEnvelope<T, S> {
338    fn from(e: TrustedEnvelope<T, S>) -> Self {
339        Self::new_unchecked(e.0)
340    }
341}
342
343impl<T: Message, S> Deref for VerifiedEnvelope<T, S> {
344    type Target = Envelope<T, S>;
345    fn deref(&self) -> &Self::Target {
346        &self.0.0
347    }
348}
349
350impl<T: Message, S> Deref for Envelope<T, S> {
351    type Target = T;
352    fn deref(&self) -> &Self::Target {
353        &self.data
354    }
355}
356
357impl<T: Message, S> DerefMut for Envelope<T, S> {
358    fn deref_mut(&mut self) -> &mut Self::Target {
359        &mut self.data
360    }
361}
362
363impl<T: Message, S> From<VerifiedEnvelope<T, S>> for Envelope<T, S> {
364    fn from(v: VerifiedEnvelope<T, S>) -> Self {
365        v.0.0
366    }
367}
368
369impl<T: Message, S> PartialEq for VerifiedEnvelope<T, S>
370where
371    Envelope<T, S>: PartialEq,
372{
373    fn eq(&self, other: &Self) -> bool {
374        self.0.0 == other.0.0
375    }
376}
377
378impl<T: Message, S> Eq for VerifiedEnvelope<T, S> where Envelope<T, S>: Eq {}
379
380impl<T, S> Display for VerifiedEnvelope<T, S>
381where
382    T: Message,
383    Envelope<T, S>: Display,
384{
385    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
386        write!(f, "{}", self.0.0)
387    }
388}
389
390/// The following implementation provides two ways to construct a
391/// VerifiedEnvelope with CertificateProof. It is implemented in this file such
392/// that we could reuse the digest without having to recompute it.
393/// We allow converting a VerifiedCertificate into a VerifiedEnvelope with
394/// CertificateProof::Certificate; and converting a VerifiedTransaction along
395/// with checkpoint information into a VerifiedEnvelope
396/// with CertificateProof::Checkpoint.
397impl<T: Message> VerifiedEnvelope<T, CertificateProof> {
398    pub fn new_from_certificate(
399        certificate: VerifiedEnvelope<T, AuthorityStrongQuorumSignInfo>,
400    ) -> Self {
401        let inner = certificate.into_inner();
402        let Envelope {
403            digest,
404            data,
405            auth_signature,
406        } = inner;
407        VerifiedEnvelope::new_unchecked(Envelope {
408            digest,
409            data,
410            auth_signature: CertificateProof::new_from_cert_sig(auth_signature),
411        })
412    }
413
414    pub fn new_from_checkpoint(
415        transaction: VerifiedEnvelope<T, EmptySignInfo>,
416        epoch: EpochId,
417        checkpoint: CheckpointSequenceNumber,
418    ) -> Self {
419        let inner = transaction.into_inner();
420        let Envelope {
421            digest,
422            data,
423            auth_signature: _,
424        } = inner;
425        VerifiedEnvelope::new_unchecked(Envelope {
426            digest,
427            data,
428            auth_signature: CertificateProof::new_from_checkpoint(epoch, checkpoint),
429        })
430    }
431
432    pub fn new_system(transaction: VerifiedEnvelope<T, EmptySignInfo>, epoch: EpochId) -> Self {
433        let inner = transaction.into_inner();
434        let Envelope {
435            digest,
436            data,
437            auth_signature: _,
438        } = inner;
439        VerifiedEnvelope::new_unchecked(Envelope {
440            digest,
441            data,
442            auth_signature: CertificateProof::new_system(epoch),
443        })
444    }
445
446    pub fn new_from_quorum_execution(
447        transaction: VerifiedEnvelope<T, EmptySignInfo>,
448        epoch: EpochId,
449    ) -> Self {
450        let inner = transaction.into_inner();
451        let Envelope {
452            digest,
453            data,
454            auth_signature: _,
455        } = inner;
456        VerifiedEnvelope::new_unchecked(Envelope {
457            digest,
458            data,
459            auth_signature: CertificateProof::QuorumExecuted(epoch),
460        })
461    }
462
463    pub fn epoch(&self) -> EpochId {
464        self.auth_signature.epoch()
465    }
466}