sui_types/
message_envelope.rs

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