1use 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 shared_crypto::intent::{Intent, IntentScope};
14
15use crate::{
16 base_types::AuthorityName,
17 committee::{Committee, EpochId},
18 crypto::{
19 AuthorityKeyPair, AuthorityQuorumSignInfo, AuthoritySignInfo, AuthoritySignInfoTrait,
20 AuthoritySignature, AuthorityStrongQuorumSignInfo, EmptySignInfo, Signer,
21 },
22 error::IotaResult,
23 executable_transaction::CertificateProof,
24 messages_checkpoint::CheckpointSequenceNumber,
25 transaction::SenderSignedData,
26};
27
28pub trait Message {
29 type DigestType: Clone + Debug;
30 const SCOPE: IntentScope;
31
32 fn scope(&self) -> IntentScope {
33 Self::SCOPE
34 }
35
36 fn digest(&self) -> Self::DigestType;
37}
38
39#[derive(Clone, Debug, Eq, Serialize, Deserialize)]
40pub struct Envelope<T: Message, S> {
41 #[serde(skip)]
42 digest: OnceCell<T::DigestType>,
43
44 data: T,
45 auth_signature: S,
46}
47
48impl<T: Message, S> Envelope<T, S> {
49 pub fn new_from_data_and_sig(data: T, sig: S) -> Self {
50 Self {
51 digest: Default::default(),
52 data,
53 auth_signature: sig,
54 }
55 }
56
57 pub fn data(&self) -> &T {
58 &self.data
59 }
60
61 pub fn into_data(self) -> T {
62 self.data
63 }
64
65 pub fn into_sig(self) -> S {
66 self.auth_signature
67 }
68
69 pub fn into_data_and_sig(self) -> (T, S) {
70 let Self {
71 data,
72 auth_signature,
73 ..
74 } = self;
75 (data, auth_signature)
76 }
77
78 pub fn into_unsigned(self) -> Envelope<T, EmptySignInfo> {
80 Envelope::<T, EmptySignInfo>::new(self.into_data())
81 }
82
83 pub fn auth_sig(&self) -> &S {
84 &self.auth_signature
85 }
86
87 pub fn auth_sig_mut_for_testing(&mut self) -> &mut S {
88 &mut self.auth_signature
89 }
90
91 pub fn digest(&self) -> &T::DigestType {
92 self.digest.get_or_init(|| self.data.digest())
93 }
94
95 pub fn data_mut_for_testing(&mut self) -> &mut T {
96 &mut self.data
97 }
98}
99
100impl<T: Message + PartialEq, S: PartialEq> PartialEq for Envelope<T, S> {
101 fn eq(&self, other: &Self) -> bool {
102 self.data == other.data && self.auth_signature == other.auth_signature
103 }
104}
105
106impl<T: Message> Envelope<T, EmptySignInfo> {
107 pub fn new(data: T) -> Self {
108 Self {
109 digest: OnceCell::new(),
110 data,
111 auth_signature: EmptySignInfo {},
112 }
113 }
114}
115
116impl<T> Envelope<T, AuthoritySignInfo>
117where
118 T: Message + Serialize,
119{
120 pub fn new(
121 epoch: EpochId,
122 data: T,
123 secret: &dyn Signer<AuthoritySignature>,
124 authority: AuthorityName,
125 ) -> Self {
126 let auth_signature = Self::sign(epoch, &data, secret, authority);
127 Self {
128 digest: OnceCell::new(),
129 data,
130 auth_signature,
131 }
132 }
133
134 pub fn sign(
135 epoch: EpochId,
136 data: &T,
137 secret: &dyn Signer<AuthoritySignature>,
138 authority: AuthorityName,
139 ) -> AuthoritySignInfo {
140 AuthoritySignInfo::new(epoch, &data, Intent::iota_app(T::SCOPE), authority, secret)
141 }
142
143 pub fn epoch(&self) -> EpochId {
144 self.auth_signature.epoch
145 }
146}
147
148impl Envelope<SenderSignedData, AuthoritySignInfo> {
149 pub fn verify_committee_sigs_only(&self, committee: &Committee) -> IotaResult {
150 self.auth_signature.verify_secure(
151 self.data(),
152 Intent::iota_app(IntentScope::SenderSignedTransaction),
153 committee,
154 )
155 }
156}
157
158impl<T, const S: bool> Envelope<T, AuthorityQuorumSignInfo<S>>
159where
160 T: Message + Serialize,
161{
162 pub fn new(
163 data: T,
164 signatures: Vec<AuthoritySignInfo>,
165 committee: &Committee,
166 ) -> IotaResult<Self> {
167 let cert = Self {
168 digest: OnceCell::new(),
169 data,
170 auth_signature: AuthorityQuorumSignInfo::<S>::new_from_auth_sign_infos(
171 signatures, committee,
172 )?,
173 };
174
175 Ok(cert)
176 }
177
178 pub fn new_from_keypairs_for_testing(
179 data: T,
180 keypairs: &[AuthorityKeyPair],
181 committee: &Committee,
182 ) -> Self {
183 let signatures = keypairs
184 .iter()
185 .map(|keypair| {
186 AuthoritySignInfo::new(
187 committee.epoch(),
188 &data,
189 Intent::iota_app(T::SCOPE),
190 keypair.public().into(),
191 keypair,
192 )
193 })
194 .collect();
195 Self::new(data, signatures, committee).unwrap()
196 }
197
198 pub fn epoch(&self) -> EpochId {
199 self.auth_signature.epoch
200 }
201}
202
203#[derive(Clone, Serialize, Deserialize)]
217pub struct TrustedEnvelope<T: Message, S>(Envelope<T, S>);
218
219impl<T, S: Debug> Debug for TrustedEnvelope<T, S>
220where
221 T: Message + Debug,
222{
223 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
224 write!(f, "{:?}", self.0)
225 }
226}
227
228impl<T: Message, S> TrustedEnvelope<T, S> {
229 pub fn into_inner(self) -> Envelope<T, S> {
230 self.0
231 }
232
233 pub fn inner(&self) -> &Envelope<T, S> {
234 &self.0
235 }
236}
237
238#[derive(Clone)]
240struct NoSer;
241static_assertions::assert_not_impl_any!(NoSer: Serialize, DeserializeOwned);
243
244#[derive(Clone)]
245pub struct VerifiedEnvelope<T: Message, S>(TrustedEnvelope<T, S>, NoSer);
246
247impl<T, S: Debug> Debug for VerifiedEnvelope<T, S>
248where
249 T: Message + Debug,
250{
251 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
252 write!(f, "{:?}", self.0.0)
253 }
254}
255
256impl<T: Message, S> VerifiedEnvelope<T, S> {
257 pub fn new_from_verified(inner: Envelope<T, S>) -> Self {
259 Self(TrustedEnvelope(inner), NoSer)
260 }
261
262 pub fn new_unchecked(inner: Envelope<T, S>) -> Self {
266 Self(TrustedEnvelope(inner), NoSer)
267 }
268
269 pub fn into_inner(self) -> Envelope<T, S> {
270 self.0.0
271 }
272
273 pub fn inner(&self) -> &Envelope<T, S> {
274 &self.0.0
275 }
276
277 pub fn into_message(self) -> T {
278 self.into_inner().into_data()
279 }
280
281 pub fn serializable_ref(&self) -> &TrustedEnvelope<T, S> {
285 &self.0
286 }
287
288 pub fn serializable(self) -> TrustedEnvelope<T, S> {
292 self.0
293 }
294
295 pub fn into_unsigned(self) -> VerifiedEnvelope<T, EmptySignInfo> {
297 VerifiedEnvelope::<T, EmptySignInfo>::new_from_verified(self.into_inner().into_unsigned())
298 }
299}
300
301impl<T: Message, S> From<TrustedEnvelope<T, S>> for VerifiedEnvelope<T, S> {
304 fn from(e: TrustedEnvelope<T, S>) -> Self {
305 Self::new_unchecked(e.0)
306 }
307}
308
309impl<T: Message, S> Deref for VerifiedEnvelope<T, S> {
310 type Target = Envelope<T, S>;
311 fn deref(&self) -> &Self::Target {
312 &self.0.0
313 }
314}
315
316impl<T: Message, S> Deref for Envelope<T, S> {
317 type Target = T;
318 fn deref(&self) -> &Self::Target {
319 &self.data
320 }
321}
322
323impl<T: Message, S> DerefMut for Envelope<T, S> {
324 fn deref_mut(&mut self) -> &mut Self::Target {
325 &mut self.data
326 }
327}
328
329impl<T: Message, S> From<VerifiedEnvelope<T, S>> for Envelope<T, S> {
330 fn from(v: VerifiedEnvelope<T, S>) -> Self {
331 v.0.0
332 }
333}
334
335impl<T: Message, S> PartialEq for VerifiedEnvelope<T, S>
336where
337 Envelope<T, S>: PartialEq,
338{
339 fn eq(&self, other: &Self) -> bool {
340 self.0.0 == other.0.0
341 }
342}
343
344impl<T: Message, S> Eq for VerifiedEnvelope<T, S> where Envelope<T, S>: Eq {}
345
346impl<T, S> Display for VerifiedEnvelope<T, S>
347where
348 T: Message,
349 Envelope<T, S>: Display,
350{
351 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
352 write!(f, "{}", self.0.0)
353 }
354}
355
356impl<T: Message> VerifiedEnvelope<T, CertificateProof> {
364 pub fn new_from_certificate(
365 certificate: VerifiedEnvelope<T, AuthorityStrongQuorumSignInfo>,
366 ) -> Self {
367 let inner = certificate.into_inner();
368 let Envelope {
369 digest,
370 data,
371 auth_signature,
372 } = inner;
373 VerifiedEnvelope::new_unchecked(Envelope {
374 digest,
375 data,
376 auth_signature: CertificateProof::new_from_cert_sig(auth_signature),
377 })
378 }
379
380 pub fn new_from_checkpoint(
381 transaction: VerifiedEnvelope<T, EmptySignInfo>,
382 epoch: EpochId,
383 checkpoint: CheckpointSequenceNumber,
384 ) -> Self {
385 let inner = transaction.into_inner();
386 let Envelope {
387 digest,
388 data,
389 auth_signature: _,
390 } = inner;
391 VerifiedEnvelope::new_unchecked(Envelope {
392 digest,
393 data,
394 auth_signature: CertificateProof::new_from_checkpoint(epoch, checkpoint),
395 })
396 }
397
398 pub fn new_system(transaction: VerifiedEnvelope<T, EmptySignInfo>, epoch: EpochId) -> Self {
399 let inner = transaction.into_inner();
400 let Envelope {
401 digest,
402 data,
403 auth_signature: _,
404 } = inner;
405 VerifiedEnvelope::new_unchecked(Envelope {
406 digest,
407 data,
408 auth_signature: CertificateProof::new_system(epoch),
409 })
410 }
411
412 pub fn new_from_quorum_execution(
413 transaction: VerifiedEnvelope<T, EmptySignInfo>,
414 epoch: EpochId,
415 ) -> Self {
416 let inner = transaction.into_inner();
417 let Envelope {
418 digest,
419 data,
420 auth_signature: _,
421 } = inner;
422 VerifiedEnvelope::new_unchecked(Envelope {
423 digest,
424 data,
425 auth_signature: CertificateProof::QuorumExecuted(epoch),
426 })
427 }
428
429 pub fn epoch(&self) -> EpochId {
430 self.auth_signature.epoch()
431 }
432}