1use std::{
6 fmt::{Debug, Display, Formatter},
7 ops::{Deref, DerefMut},
8};
9
10use fastcrypto::traits::KeyPair;
11use iota_sdk_types::{
12 SenderSignedTransaction,
13 crypto::{Intent, IntentScope},
14};
15use once_cell::sync::OnceCell;
16use serde::{Deserialize, Serialize, de::DeserializeOwned};
17use serde_name::{DeserializeNameAdapter, SerializeNameAdapter};
18use tracing::instrument;
19
20use crate::{
21 base_types::AuthorityName,
22 committee::{Committee, EpochId},
23 crypto::{
24 AuthorityKeyPair, AuthorityQuorumSignInfo, AuthoritySignInfo, AuthoritySignInfoTrait,
25 AuthoritySignature, AuthorityStrongQuorumSignInfo, EmptySignInfo, Signer,
26 },
27 error::IotaResult,
28 executable_transaction::CertificateProof,
29 messages_checkpoint::CheckpointSequenceNumber,
30};
31
32pub trait Message {
33 type DigestType: Clone + Debug;
34 const SCOPE: IntentScope;
35
36 fn scope(&self) -> IntentScope {
37 Self::SCOPE
38 }
39
40 fn digest(&self) -> Self::DigestType;
41}
42
43#[derive(Clone, Debug, Eq, Serialize, Deserialize)]
44#[serde(remote = "Envelope")]
45pub struct Envelope<T: Message, S> {
46 #[serde(skip)]
47 digest: OnceCell<T::DigestType>,
48
49 data: T,
50 auth_signature: S,
51}
52
53impl<'de, T, S> Deserialize<'de> for Envelope<T, S>
54where
55 T: Message + Deserialize<'de>,
56 S: Deserialize<'de>,
57{
58 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
59 where
60 D: serde::de::Deserializer<'de>,
61 {
62 Envelope::deserialize(DeserializeNameAdapter::new(
63 deserializer,
64 std::any::type_name::<Self>(),
65 ))
66 }
67}
68
69impl<T, Sig> Serialize for Envelope<T, Sig>
70where
71 T: Message + Serialize,
72 Sig: Serialize,
73{
74 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
75 where
76 S: serde::ser::Serializer,
77 {
78 Envelope::serialize(
79 self,
80 SerializeNameAdapter::new(serializer, std::any::type_name::<Self>()),
81 )
82 }
83}
84
85impl<T: Message, S> Envelope<T, S> {
86 pub fn new_from_data_and_sig(data: T, sig: S) -> Self {
87 Self {
88 digest: Default::default(),
89 data,
90 auth_signature: sig,
91 }
92 }
93
94 pub fn data(&self) -> &T {
95 &self.data
96 }
97
98 pub fn into_data(self) -> T {
99 self.data
100 }
101
102 pub fn into_sig(self) -> S {
103 self.auth_signature
104 }
105
106 pub fn into_data_and_sig(self) -> (T, S) {
107 let Self {
108 data,
109 auth_signature,
110 ..
111 } = self;
112 (data, auth_signature)
113 }
114
115 pub fn into_unsigned(self) -> Envelope<T, EmptySignInfo> {
117 Envelope::<T, EmptySignInfo>::new(self.into_data())
118 }
119
120 pub fn auth_sig(&self) -> &S {
121 &self.auth_signature
122 }
123
124 pub fn auth_sig_mut_for_testing(&mut self) -> &mut S {
125 &mut self.auth_signature
126 }
127
128 pub fn digest(&self) -> &T::DigestType {
129 self.digest.get_or_init(|| self.data.digest())
130 }
131
132 pub fn data_mut_for_testing(&mut self) -> &mut T {
133 &mut self.data
134 }
135}
136
137impl<T: Message + PartialEq, S: PartialEq> PartialEq for Envelope<T, S> {
138 fn eq(&self, other: &Self) -> bool {
139 self.data == other.data && self.auth_signature == other.auth_signature
140 }
141}
142
143impl<T: Message> Envelope<T, EmptySignInfo> {
144 pub fn new(data: T) -> Self {
145 Self {
146 digest: OnceCell::new(),
147 data,
148 auth_signature: EmptySignInfo {},
149 }
150 }
151}
152
153impl<T> Envelope<T, AuthoritySignInfo>
154where
155 T: Message + Serialize,
156{
157 pub fn new(
158 epoch: EpochId,
159 data: T,
160 secret: &dyn Signer<AuthoritySignature>,
161 authority: AuthorityName,
162 ) -> Self {
163 let auth_signature = Self::sign(epoch, &data, secret, authority);
164 Self {
165 digest: OnceCell::new(),
166 data,
167 auth_signature,
168 }
169 }
170
171 pub fn sign(
172 epoch: EpochId,
173 data: &T,
174 secret: &dyn Signer<AuthoritySignature>,
175 authority: AuthorityName,
176 ) -> AuthoritySignInfo {
177 AuthoritySignInfo::new(epoch, &data, Intent::iota_app(T::SCOPE), authority, secret)
178 }
179
180 pub fn epoch(&self) -> EpochId {
181 self.auth_signature.epoch
182 }
183}
184
185impl Envelope<SenderSignedTransaction, AuthoritySignInfo> {
186 #[instrument(level = "trace", skip_all)]
187 pub fn verify_committee_sigs_only(&self, committee: &Committee) -> IotaResult {
188 self.auth_signature.verify_secure(
189 self.data(),
190 Intent::iota_app(IntentScope::SenderSignedTransaction),
191 committee,
192 )
193 }
194}
195
196impl<T, const S: bool> Envelope<T, AuthorityQuorumSignInfo<S>>
197where
198 T: Message + Serialize,
199{
200 pub fn new(
201 data: T,
202 signatures: Vec<AuthoritySignInfo>,
203 committee: &Committee,
204 ) -> IotaResult<Self> {
205 let cert = Self {
206 digest: OnceCell::new(),
207 data,
208 auth_signature: AuthorityQuorumSignInfo::<S>::new_from_auth_sign_infos(
209 signatures, committee,
210 )?,
211 };
212
213 Ok(cert)
214 }
215
216 pub fn new_from_keypairs_for_testing(
217 data: T,
218 keypairs: &[AuthorityKeyPair],
219 committee: &Committee,
220 ) -> Self {
221 let signatures = keypairs
222 .iter()
223 .map(|keypair| {
224 AuthoritySignInfo::new(
225 committee.epoch(),
226 &data,
227 Intent::iota_app(T::SCOPE),
228 keypair.public().into(),
229 keypair,
230 )
231 })
232 .collect();
233 Self::new(data, signatures, committee).unwrap()
234 }
235
236 pub fn epoch(&self) -> EpochId {
237 self.auth_signature.epoch
238 }
239}
240
241#[derive(Clone, Serialize, Deserialize)]
255pub struct TrustedEnvelope<T: Message, S>(Envelope<T, S>);
256
257impl<T, S: Debug> Debug for TrustedEnvelope<T, S>
258where
259 T: Message + Debug,
260{
261 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
262 write!(f, "{:?}", self.0)
263 }
264}
265
266impl<T: Message, S> TrustedEnvelope<T, S> {
267 pub fn into_inner(self) -> Envelope<T, S> {
268 self.0
269 }
270
271 pub fn inner(&self) -> &Envelope<T, S> {
272 &self.0
273 }
274}
275
276#[derive(Clone)]
278struct NoSer;
279static_assertions::assert_not_impl_any!(NoSer: Serialize, DeserializeOwned);
281
282#[derive(Clone)]
283pub struct VerifiedEnvelope<T: Message, S>(TrustedEnvelope<T, S>, NoSer);
284
285impl<T, S: Debug> Debug for VerifiedEnvelope<T, S>
286where
287 T: Message + Debug,
288{
289 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
290 write!(f, "{:?}", self.0.0)
291 }
292}
293
294impl<T: Message, S> VerifiedEnvelope<T, S> {
295 pub fn new_from_verified(inner: Envelope<T, S>) -> Self {
297 Self(TrustedEnvelope(inner), NoSer)
298 }
299
300 pub fn new_unchecked(inner: Envelope<T, S>) -> Self {
304 Self(TrustedEnvelope(inner), NoSer)
305 }
306
307 pub fn into_inner(self) -> Envelope<T, S> {
308 self.0.0
309 }
310
311 pub fn inner(&self) -> &Envelope<T, S> {
312 &self.0.0
313 }
314
315 pub fn into_message(self) -> T {
316 self.into_inner().into_data()
317 }
318
319 pub fn serializable_ref(&self) -> &TrustedEnvelope<T, S> {
323 &self.0
324 }
325
326 pub fn serializable(self) -> TrustedEnvelope<T, S> {
330 self.0
331 }
332
333 pub fn into_unsigned(self) -> VerifiedEnvelope<T, EmptySignInfo> {
335 VerifiedEnvelope::<T, EmptySignInfo>::new_from_verified(self.into_inner().into_unsigned())
336 }
337}
338
339impl<T: Message, S> From<TrustedEnvelope<T, S>> for VerifiedEnvelope<T, S> {
342 fn from(e: TrustedEnvelope<T, S>) -> Self {
343 Self::new_unchecked(e.0)
344 }
345}
346
347impl<T: Message, S> Deref for VerifiedEnvelope<T, S> {
348 type Target = Envelope<T, S>;
349 fn deref(&self) -> &Self::Target {
350 &self.0.0
351 }
352}
353
354impl<T: Message, S> Deref for Envelope<T, S> {
355 type Target = T;
356 fn deref(&self) -> &Self::Target {
357 &self.data
358 }
359}
360
361impl<T: Message, S> DerefMut for Envelope<T, S> {
362 fn deref_mut(&mut self) -> &mut Self::Target {
363 &mut self.data
364 }
365}
366
367impl<T: Message, S> From<VerifiedEnvelope<T, S>> for Envelope<T, S> {
368 fn from(v: VerifiedEnvelope<T, S>) -> Self {
369 v.0.0
370 }
371}
372
373impl<T: Message, S> PartialEq for VerifiedEnvelope<T, S>
374where
375 Envelope<T, S>: PartialEq,
376{
377 fn eq(&self, other: &Self) -> bool {
378 self.0.0 == other.0.0
379 }
380}
381
382impl<T: Message, S> Eq for VerifiedEnvelope<T, S> where Envelope<T, S>: Eq {}
383
384impl<T, S> Display for VerifiedEnvelope<T, S>
385where
386 T: Message,
387 Envelope<T, S>: Display,
388{
389 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
390 write!(f, "{}", self.0.0)
391 }
392}
393
394impl<T: Message> VerifiedEnvelope<T, CertificateProof> {
402 pub fn new_from_certificate(
403 certificate: VerifiedEnvelope<T, AuthorityStrongQuorumSignInfo>,
404 ) -> Self {
405 let inner = certificate.into_inner();
406 let Envelope {
407 digest,
408 data,
409 auth_signature,
410 } = inner;
411 VerifiedEnvelope::new_unchecked(Envelope {
412 digest,
413 data,
414 auth_signature: CertificateProof::new_from_cert_sig(auth_signature),
415 })
416 }
417
418 pub fn new_from_checkpoint(
419 transaction: VerifiedEnvelope<T, EmptySignInfo>,
420 epoch: EpochId,
421 checkpoint: CheckpointSequenceNumber,
422 ) -> Self {
423 let inner = transaction.into_inner();
424 let Envelope {
425 digest,
426 data,
427 auth_signature: _,
428 } = inner;
429 VerifiedEnvelope::new_unchecked(Envelope {
430 digest,
431 data,
432 auth_signature: CertificateProof::new_from_checkpoint(epoch, checkpoint),
433 })
434 }
435
436 pub fn new_system(transaction: VerifiedEnvelope<T, EmptySignInfo>, epoch: EpochId) -> Self {
437 let inner = transaction.into_inner();
438 let Envelope {
439 digest,
440 data,
441 auth_signature: _,
442 } = inner;
443 VerifiedEnvelope::new_unchecked(Envelope {
444 digest,
445 data,
446 auth_signature: CertificateProof::new_system(epoch),
447 })
448 }
449
450 pub fn new_from_quorum_execution(
451 transaction: VerifiedEnvelope<T, EmptySignInfo>,
452 epoch: EpochId,
453 ) -> Self {
454 let inner = transaction.into_inner();
455 let Envelope {
456 digest,
457 data,
458 auth_signature: _,
459 } = inner;
460 VerifiedEnvelope::new_unchecked(Envelope {
461 digest,
462 data,
463 auth_signature: CertificateProof::QuorumExecuted(epoch),
464 })
465 }
466
467 pub fn epoch(&self) -> EpochId {
468 self.auth_signature.epoch()
469 }
470}