1use crate::base_types::{AuthorityName, ConsensusObjectSequenceKey, ObjectRef, TransactionDigest};
5use crate::base_types::{ConciseableName, ObjectID, SequenceNumber};
6use crate::committee::EpochId;
7use crate::digests::{AdditionalConsensusStateDigest, ConsensusCommitDigest};
8use crate::error::{SuiError, SuiErrorKind};
9use crate::execution::ExecutionTimeObservationKey;
10use crate::messages_checkpoint::{
11 CheckpointDigest, CheckpointSequenceNumber, CheckpointSignatureMessage,
12};
13use crate::supported_protocol_versions::{
14 Chain, SupportedProtocolVersions, SupportedProtocolVersionsWithHashes,
15};
16use crate::transaction::{CertifiedTransaction, PlainTransactionWithClaims, Transaction};
17use byteorder::{BigEndian, ReadBytesExt};
18use bytes::Bytes;
19use consensus_types::block::{BlockRef, PING_TRANSACTION_INDEX, TransactionIndex};
20use fastcrypto::error::FastCryptoResult;
21use fastcrypto::groups::bls12381;
22use fastcrypto_tbls::dkg_v1;
23use fastcrypto_zkp::bn254::zk_login::{JWK, JwkId};
24use schemars::JsonSchema;
25use serde::{Deserialize, Serialize};
26use std::collections::hash_map::DefaultHasher;
27use std::fmt::{Debug, Formatter};
28use std::hash::{Hash, Hasher};
29use std::sync::Arc;
30use std::time::{Duration, SystemTime, UNIX_EPOCH};
31
32pub type AuthorityIndex = u32;
35
36pub type Round = u64;
39
40pub type TimestampMs = u64;
43
44#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
46pub struct ConsensusPosition {
47 pub epoch: EpochId,
49 pub block: BlockRef,
51 pub index: TransactionIndex,
53}
54
55impl ConsensusPosition {
56 pub fn into_raw(self) -> Result<Bytes, SuiError> {
57 bcs::to_bytes(&self)
58 .map_err(|e| {
59 SuiErrorKind::GrpcMessageSerializeError {
60 type_info: "ConsensusPosition".to_string(),
61 error: e.to_string(),
62 }
63 .into()
64 })
65 .map(Bytes::from)
66 }
67
68 pub fn ping(epoch: EpochId, block: BlockRef) -> Self {
71 Self {
72 epoch,
73 block,
74 index: PING_TRANSACTION_INDEX,
75 }
76 }
77}
78
79impl TryFrom<&[u8]> for ConsensusPosition {
80 type Error = SuiError;
81
82 fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
83 bcs::from_bytes(bytes).map_err(|e| {
84 SuiErrorKind::GrpcMessageDeserializeError {
85 type_info: "ConsensusPosition".to_string(),
86 error: e.to_string(),
87 }
88 .into()
89 })
90 }
91}
92
93impl std::fmt::Display for ConsensusPosition {
94 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
95 write!(f, "P(E{}, {}, {})", self.epoch, self.block, self.index)
96 }
97}
98
99impl std::fmt::Debug for ConsensusPosition {
100 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
101 write!(f, "P(E{}, {:?}, {})", self.epoch, self.block, self.index)
102 }
103}
104
105#[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize)]
108pub struct ConsensusCommitPrologue {
109 pub epoch: u64,
111 pub round: u64,
113 pub commit_timestamp_ms: TimestampMs,
115}
116
117#[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize)]
118pub struct ConsensusCommitPrologueV2 {
119 pub epoch: u64,
121 pub round: u64,
123 pub commit_timestamp_ms: TimestampMs,
125 pub consensus_commit_digest: ConsensusCommitDigest,
127}
128
129#[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize, JsonSchema)]
130pub enum ConsensusDeterminedVersionAssignments {
131 CancelledTransactions(Vec<(TransactionDigest, Vec<(ObjectID, SequenceNumber)>)>),
133 CancelledTransactionsV2(
134 Vec<(
135 TransactionDigest,
136 Vec<(ConsensusObjectSequenceKey, SequenceNumber)>,
137 )>,
138 ),
139}
140
141impl ConsensusDeterminedVersionAssignments {
142 pub fn empty_for_testing() -> Self {
143 Self::CancelledTransactions(Vec::new())
144 }
145}
146
147#[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize)]
148pub struct ConsensusCommitPrologueV3 {
149 pub epoch: u64,
151 pub round: u64,
153 pub sub_dag_index: Option<u64>,
156 pub commit_timestamp_ms: TimestampMs,
158 pub consensus_commit_digest: ConsensusCommitDigest,
160 pub consensus_determined_version_assignments: ConsensusDeterminedVersionAssignments,
162}
163
164#[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize)]
165pub struct ConsensusCommitPrologueV4 {
166 pub epoch: u64,
168 pub round: u64,
170 pub sub_dag_index: Option<u64>,
173 pub commit_timestamp_ms: TimestampMs,
175 pub consensus_commit_digest: ConsensusCommitDigest,
177 pub consensus_determined_version_assignments: ConsensusDeterminedVersionAssignments,
179 pub additional_state_digest: AdditionalConsensusStateDigest,
182}
183
184static MAX_TOTAL_JWK_SIZE: usize = 4096;
187
188pub fn check_total_jwk_size(id: &JwkId, jwk: &JWK) -> bool {
189 id.iss.len() + id.kid.len() + jwk.kty.len() + jwk.alg.len() + jwk.e.len() + jwk.n.len()
190 <= MAX_TOTAL_JWK_SIZE
191}
192
193#[derive(Serialize, Deserialize, Clone, Debug)]
194pub struct ConsensusTransaction {
195 pub tracking_id: [u8; 8],
198 pub kind: ConsensusTransactionKind,
199}
200
201impl ConsensusTransaction {
202 pub fn local_display(&self) -> String {
204 match &self.kind {
205 ConsensusTransactionKind::CertifiedTransaction(cert) => {
206 format!("Certified({})", cert.digest())
207 }
208 ConsensusTransactionKind::CheckpointSignature(data) => {
209 format!(
210 "CkptSig({}, {})",
211 data.summary.sequence_number,
212 data.summary.digest()
213 )
214 }
215 ConsensusTransactionKind::CheckpointSignatureV2(data) => {
216 format!(
217 "CkptSigV2({}, {})",
218 data.summary.sequence_number,
219 data.summary.digest()
220 )
221 }
222 ConsensusTransactionKind::EndOfPublish(..) => "EOP".to_string(),
223 ConsensusTransactionKind::CapabilityNotification(..) => "Cap".to_string(),
224 ConsensusTransactionKind::CapabilityNotificationV2(..) => "CapV2".to_string(),
225 ConsensusTransactionKind::NewJWKFetched(..) => "NewJWKFetched".to_string(),
226 ConsensusTransactionKind::RandomnessStateUpdate(..) => "RandStateUpdate".to_string(),
227 ConsensusTransactionKind::RandomnessDkgMessage(..) => "RandDkg".to_string(),
228 ConsensusTransactionKind::RandomnessDkgConfirmation(..) => "RandDkgConf".to_string(),
229 ConsensusTransactionKind::ExecutionTimeObservation(..) => "ExecTimeOb".to_string(),
230 ConsensusTransactionKind::UserTransaction(tx) => {
231 format!("User({})", tx.digest())
232 }
233 ConsensusTransactionKind::UserTransactionV2(tx) => {
234 format!("UserV2({})", tx.tx().digest())
235 }
236 }
237 }
238}
239
240#[derive(Serialize, Deserialize, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
242pub enum ConsensusTransactionKey {
243 Certificate(TransactionDigest),
244 CheckpointSignature(AuthorityName, CheckpointSequenceNumber),
246 EndOfPublish(AuthorityName),
247 CapabilityNotification(AuthorityName, u64 ),
248 NewJWKFetched(Box<(AuthorityName, JwkId, JWK)>),
251 RandomnessDkgMessage(AuthorityName),
252 RandomnessDkgConfirmation(AuthorityName),
253 ExecutionTimeObservation(AuthorityName, u64 ),
254 CheckpointSignatureV2(AuthorityName, CheckpointSequenceNumber, CheckpointDigest),
256}
257
258impl Debug for ConsensusTransactionKey {
259 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
260 match self {
261 Self::Certificate(digest) => write!(f, "Certificate({:?})", digest),
262 Self::CheckpointSignature(name, seq) => {
263 write!(f, "CheckpointSignature({:?}, {:?})", name.concise(), seq)
264 }
265 Self::CheckpointSignatureV2(name, seq, digest) => write!(
266 f,
267 "CheckpointSignatureV2({:?}, {:?}, {:?})",
268 name.concise(),
269 seq,
270 digest
271 ),
272 Self::EndOfPublish(name) => write!(f, "EndOfPublish({:?})", name.concise()),
273 Self::CapabilityNotification(name, generation) => write!(
274 f,
275 "CapabilityNotification({:?}, {:?})",
276 name.concise(),
277 generation
278 ),
279 Self::NewJWKFetched(key) => {
280 let (authority, id, jwk) = &**key;
281 write!(
282 f,
283 "NewJWKFetched({:?}, {:?}, {:?})",
284 authority.concise(),
285 id,
286 jwk
287 )
288 }
289 Self::RandomnessDkgMessage(name) => {
290 write!(f, "RandomnessDkgMessage({:?})", name.concise())
291 }
292 Self::RandomnessDkgConfirmation(name) => {
293 write!(f, "RandomnessDkgConfirmation({:?})", name.concise())
294 }
295 Self::ExecutionTimeObservation(name, generation) => {
296 write!(
297 f,
298 "ExecutionTimeObservation({:?}, {generation:?})",
299 name.concise()
300 )
301 }
302 }
303 }
304}
305
306#[derive(Serialize, Deserialize, Clone, Hash)]
310pub struct AuthorityCapabilitiesV1 {
311 pub authority: AuthorityName,
313 pub generation: u64,
319
320 pub supported_protocol_versions: SupportedProtocolVersions,
322
323 pub available_system_packages: Vec<ObjectRef>,
326}
327
328impl Debug for AuthorityCapabilitiesV1 {
329 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
330 f.debug_struct("AuthorityCapabilities")
331 .field("authority", &self.authority.concise())
332 .field("generation", &self.generation)
333 .field(
334 "supported_protocol_versions",
335 &self.supported_protocol_versions,
336 )
337 .field("available_system_packages", &self.available_system_packages)
338 .finish()
339 }
340}
341
342#[derive(Serialize, Deserialize, Clone, Hash)]
345pub struct AuthorityCapabilitiesV2 {
346 pub authority: AuthorityName,
348 pub generation: u64,
354
355 pub supported_protocol_versions: SupportedProtocolVersionsWithHashes,
357
358 pub available_system_packages: Vec<ObjectRef>,
361}
362
363impl Debug for AuthorityCapabilitiesV2 {
364 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
365 f.debug_struct("AuthorityCapabilities")
366 .field("authority", &self.authority.concise())
367 .field("generation", &self.generation)
368 .field(
369 "supported_protocol_versions",
370 &self.supported_protocol_versions,
371 )
372 .field("available_system_packages", &self.available_system_packages)
373 .finish()
374 }
375}
376
377impl AuthorityCapabilitiesV2 {
378 pub fn new(
379 authority: AuthorityName,
380 chain: Chain,
381 supported_protocol_versions: SupportedProtocolVersions,
382 available_system_packages: Vec<ObjectRef>,
383 ) -> Self {
384 let generation = SystemTime::now()
385 .duration_since(UNIX_EPOCH)
386 .expect("Sui did not exist prior to 1970")
387 .as_millis()
388 .try_into()
389 .expect("This build of sui is not supported in the year 500,000,000");
390 Self {
391 authority,
392 generation,
393 supported_protocol_versions:
394 SupportedProtocolVersionsWithHashes::from_supported_versions(
395 supported_protocol_versions,
396 chain,
397 ),
398 available_system_packages,
399 }
400 }
401}
402
403#[derive(Debug, Default, PartialEq, Eq, Hash, Clone, Serialize, Deserialize)]
406pub struct ExecutionTimeObservation {
407 pub authority: AuthorityName,
409 pub generation: u64,
412
413 pub estimates: Vec<(ExecutionTimeObservationKey, Duration)>,
415}
416
417impl ExecutionTimeObservation {
418 pub fn new(
419 authority: AuthorityName,
420 generation: u64,
421 estimates: Vec<(ExecutionTimeObservationKey, Duration)>,
422 ) -> Self {
423 Self {
424 authority,
425 generation,
426 estimates,
427 }
428 }
429}
430
431#[derive(Serialize, Deserialize, Clone, Debug)]
432pub enum ConsensusTransactionKind {
433 CertifiedTransaction(Box<CertifiedTransaction>),
434 CheckpointSignature(Box<CheckpointSignatureMessage>), EndOfPublish(AuthorityName),
436
437 CapabilityNotification(AuthorityCapabilitiesV1), NewJWKFetched(AuthorityName, JwkId, JWK),
440 RandomnessStateUpdate(u64, Vec<u8>), RandomnessDkgMessage(AuthorityName, Vec<u8>),
445 RandomnessDkgConfirmation(AuthorityName, Vec<u8>),
449
450 CapabilityNotificationV2(AuthorityCapabilitiesV2),
451
452 UserTransaction(Box<Transaction>),
453
454 ExecutionTimeObservation(ExecutionTimeObservation),
455 CheckpointSignatureV2(Box<CheckpointSignatureMessage>),
457
458 UserTransactionV2(Box<PlainTransactionWithClaims>),
462}
463
464impl ConsensusTransactionKind {
465 pub fn as_user_transaction(&self) -> Option<&Transaction> {
466 match self {
467 ConsensusTransactionKind::UserTransaction(tx) => Some(tx),
468 ConsensusTransactionKind::UserTransactionV2(tx) => Some(tx.tx()),
469 _ => None,
470 }
471 }
472
473 pub fn into_user_transaction(self) -> Option<Transaction> {
474 match self {
475 ConsensusTransactionKind::UserTransaction(tx) => Some(*tx),
476 ConsensusTransactionKind::UserTransactionV2(tx) => Some(tx.into_tx()),
477 _ => None,
478 }
479 }
480}
481
482#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
483#[allow(clippy::large_enum_variant)]
484pub enum VersionedDkgMessage {
485 V0(), V1(dkg_v1::Message<bls12381::G2Element, bls12381::G2Element>),
487}
488
489#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
490pub enum VersionedDkgConfirmation {
491 V0(), V1(dkg_v1::Confirmation<bls12381::G2Element>),
493}
494
495impl Debug for VersionedDkgMessage {
496 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
497 match self {
498 VersionedDkgMessage::V0() => write!(f, "Deprecated VersionedDkgMessage version 0"),
499 VersionedDkgMessage::V1(msg) => write!(
500 f,
501 "DKG V1 Message with sender={}, vss_pk.degree={}, encrypted_shares.len()={}",
502 msg.sender,
503 msg.vss_pk.degree(),
504 msg.encrypted_shares.len(),
505 ),
506 }
507 }
508}
509
510impl VersionedDkgMessage {
511 pub fn sender(&self) -> u16 {
512 match self {
513 VersionedDkgMessage::V0() => panic!("BUG: invalid VersionedDkgMessage version"),
514 VersionedDkgMessage::V1(msg) => msg.sender,
515 }
516 }
517
518 pub fn create(
519 dkg_version: u64,
520 party: Arc<dkg_v1::Party<bls12381::G2Element, bls12381::G2Element>>,
521 ) -> FastCryptoResult<VersionedDkgMessage> {
522 assert_eq!(dkg_version, 1, "BUG: invalid DKG version");
523 let msg = party.create_message(&mut rand::thread_rng())?;
524 Ok(VersionedDkgMessage::V1(msg))
525 }
526
527 pub fn unwrap_v1(self) -> dkg_v1::Message<bls12381::G2Element, bls12381::G2Element> {
528 match self {
529 VersionedDkgMessage::V1(msg) => msg,
530 _ => panic!("BUG: expected V1 message"),
531 }
532 }
533
534 pub fn is_valid_version(&self, dkg_version: u64) -> bool {
535 matches!((self, dkg_version), (VersionedDkgMessage::V1(_), 1))
536 }
537}
538
539impl VersionedDkgConfirmation {
540 pub fn sender(&self) -> u16 {
541 match self {
542 VersionedDkgConfirmation::V0() => {
543 panic!("BUG: invalid VersionedDkgConfirmation version")
544 }
545 VersionedDkgConfirmation::V1(msg) => msg.sender,
546 }
547 }
548
549 pub fn num_of_complaints(&self) -> usize {
550 match self {
551 VersionedDkgConfirmation::V0() => {
552 panic!("BUG: invalid VersionedDkgConfirmation version")
553 }
554 VersionedDkgConfirmation::V1(msg) => msg.complaints.len(),
555 }
556 }
557
558 pub fn unwrap_v1(&self) -> &dkg_v1::Confirmation<bls12381::G2Element> {
559 match self {
560 VersionedDkgConfirmation::V1(msg) => msg,
561 _ => panic!("BUG: expected V1 confirmation"),
562 }
563 }
564
565 pub fn is_valid_version(&self, dkg_version: u64) -> bool {
566 matches!((self, dkg_version), (VersionedDkgConfirmation::V1(_), 1))
567 }
568}
569
570impl ConsensusTransaction {
571 pub fn new_certificate_message(
572 authority: &AuthorityName,
573 certificate: CertifiedTransaction,
574 ) -> Self {
575 let mut hasher = DefaultHasher::new();
576 let tx_digest = certificate.digest();
577 tx_digest.hash(&mut hasher);
578 authority.hash(&mut hasher);
579 let tracking_id = hasher.finish().to_le_bytes();
580 Self {
581 tracking_id,
582 kind: ConsensusTransactionKind::CertifiedTransaction(Box::new(certificate)),
583 }
584 }
585
586 pub fn new_user_transaction_message(authority: &AuthorityName, tx: Transaction) -> Self {
587 let mut hasher = DefaultHasher::new();
588 let tx_digest = tx.digest();
589 tx_digest.hash(&mut hasher);
590 authority.hash(&mut hasher);
591 let tracking_id = hasher.finish().to_le_bytes();
592 Self {
593 tracking_id,
594 kind: ConsensusTransactionKind::UserTransaction(Box::new(tx)),
595 }
596 }
597
598 pub fn new_user_transaction_v2_message(
599 authority: &AuthorityName,
600 tx: PlainTransactionWithClaims,
601 ) -> Self {
602 let mut hasher = DefaultHasher::new();
603 let tx_digest = tx.tx().digest();
604 tx_digest.hash(&mut hasher);
605 authority.hash(&mut hasher);
606 let tracking_id = hasher.finish().to_le_bytes();
607 Self {
608 tracking_id,
609 kind: ConsensusTransactionKind::UserTransactionV2(Box::new(tx)),
610 }
611 }
612
613 pub fn new_checkpoint_signature_message_v2(data: CheckpointSignatureMessage) -> Self {
614 let mut hasher = DefaultHasher::new();
615 data.summary.auth_sig().signature.hash(&mut hasher);
616 let tracking_id = hasher.finish().to_le_bytes();
617 Self {
618 tracking_id,
619 kind: ConsensusTransactionKind::CheckpointSignatureV2(Box::new(data)),
620 }
621 }
622
623 pub fn new_end_of_publish(authority: AuthorityName) -> Self {
624 let mut hasher = DefaultHasher::new();
625 authority.hash(&mut hasher);
626 let tracking_id = hasher.finish().to_le_bytes();
627 Self {
628 tracking_id,
629 kind: ConsensusTransactionKind::EndOfPublish(authority),
630 }
631 }
632
633 pub fn new_capability_notification_v2(capabilities: AuthorityCapabilitiesV2) -> Self {
634 let mut hasher = DefaultHasher::new();
635 capabilities.hash(&mut hasher);
636 let tracking_id = hasher.finish().to_le_bytes();
637 Self {
638 tracking_id,
639 kind: ConsensusTransactionKind::CapabilityNotificationV2(capabilities),
640 }
641 }
642
643 pub fn new_mysticeti_certificate(
644 round: u64,
645 offset: u64,
646 certificate: CertifiedTransaction,
647 ) -> Self {
648 let mut hasher = DefaultHasher::new();
649 let tx_digest = certificate.digest();
650 tx_digest.hash(&mut hasher);
651 round.hash(&mut hasher);
652 offset.hash(&mut hasher);
653 let tracking_id = hasher.finish().to_le_bytes();
654 Self {
655 tracking_id,
656 kind: ConsensusTransactionKind::CertifiedTransaction(Box::new(certificate)),
657 }
658 }
659
660 pub fn new_jwk_fetched(authority: AuthorityName, id: JwkId, jwk: JWK) -> Self {
661 let mut hasher = DefaultHasher::new();
662 id.hash(&mut hasher);
663 let tracking_id = hasher.finish().to_le_bytes();
664 Self {
665 tracking_id,
666 kind: ConsensusTransactionKind::NewJWKFetched(authority, id, jwk),
667 }
668 }
669
670 pub fn new_randomness_dkg_message(
671 authority: AuthorityName,
672 versioned_message: &VersionedDkgMessage,
673 ) -> Self {
674 let message =
675 bcs::to_bytes(versioned_message).expect("message serialization should not fail");
676 let mut hasher = DefaultHasher::new();
677 message.hash(&mut hasher);
678 let tracking_id = hasher.finish().to_le_bytes();
679 Self {
680 tracking_id,
681 kind: ConsensusTransactionKind::RandomnessDkgMessage(authority, message),
682 }
683 }
684 pub fn new_randomness_dkg_confirmation(
685 authority: AuthorityName,
686 versioned_confirmation: &VersionedDkgConfirmation,
687 ) -> Self {
688 let confirmation =
689 bcs::to_bytes(versioned_confirmation).expect("message serialization should not fail");
690 let mut hasher = DefaultHasher::new();
691 confirmation.hash(&mut hasher);
692 let tracking_id = hasher.finish().to_le_bytes();
693 Self {
694 tracking_id,
695 kind: ConsensusTransactionKind::RandomnessDkgConfirmation(authority, confirmation),
696 }
697 }
698
699 pub fn new_execution_time_observation(observation: ExecutionTimeObservation) -> Self {
700 let mut hasher = DefaultHasher::new();
701 observation.hash(&mut hasher);
702 let tracking_id = hasher.finish().to_le_bytes();
703 Self {
704 tracking_id,
705 kind: ConsensusTransactionKind::ExecutionTimeObservation(observation),
706 }
707 }
708
709 pub fn get_tracking_id(&self) -> u64 {
710 (&self.tracking_id[..])
711 .read_u64::<BigEndian>()
712 .unwrap_or_default()
713 }
714
715 pub fn key(&self) -> ConsensusTransactionKey {
716 match &self.kind {
717 ConsensusTransactionKind::CertifiedTransaction(cert) => {
718 ConsensusTransactionKey::Certificate(*cert.digest())
719 }
720 ConsensusTransactionKind::CheckpointSignature(data) => {
721 ConsensusTransactionKey::CheckpointSignature(
722 data.summary.auth_sig().authority,
723 data.summary.sequence_number,
724 )
725 }
726 ConsensusTransactionKind::CheckpointSignatureV2(data) => {
727 ConsensusTransactionKey::CheckpointSignatureV2(
728 data.summary.auth_sig().authority,
729 data.summary.sequence_number,
730 *data.summary.digest(),
731 )
732 }
733 ConsensusTransactionKind::EndOfPublish(authority) => {
734 ConsensusTransactionKey::EndOfPublish(*authority)
735 }
736 ConsensusTransactionKind::CapabilityNotification(cap) => {
737 ConsensusTransactionKey::CapabilityNotification(cap.authority, cap.generation)
738 }
739 ConsensusTransactionKind::CapabilityNotificationV2(cap) => {
740 ConsensusTransactionKey::CapabilityNotification(cap.authority, cap.generation)
741 }
742 ConsensusTransactionKind::NewJWKFetched(authority, id, key) => {
743 ConsensusTransactionKey::NewJWKFetched(Box::new((
744 *authority,
745 id.clone(),
746 key.clone(),
747 )))
748 }
749 ConsensusTransactionKind::RandomnessStateUpdate(_, _) => {
750 unreachable!(
751 "there should never be a RandomnessStateUpdate with SequencedConsensusTransactionKind::External"
752 )
753 }
754 ConsensusTransactionKind::RandomnessDkgMessage(authority, _) => {
755 ConsensusTransactionKey::RandomnessDkgMessage(*authority)
756 }
757 ConsensusTransactionKind::RandomnessDkgConfirmation(authority, _) => {
758 ConsensusTransactionKey::RandomnessDkgConfirmation(*authority)
759 }
760 ConsensusTransactionKind::UserTransaction(tx) => {
761 ConsensusTransactionKey::Certificate(*tx.digest())
765 }
766 ConsensusTransactionKind::UserTransactionV2(tx) => {
767 ConsensusTransactionKey::Certificate(*tx.tx().digest())
771 }
772 ConsensusTransactionKind::ExecutionTimeObservation(msg) => {
773 ConsensusTransactionKey::ExecutionTimeObservation(msg.authority, msg.generation)
774 }
775 }
776 }
777
778 pub fn is_dkg(&self) -> bool {
779 matches!(
780 self.kind,
781 ConsensusTransactionKind::RandomnessDkgMessage(_, _)
782 | ConsensusTransactionKind::RandomnessDkgConfirmation(_, _)
783 )
784 }
785
786 pub fn is_mfp_transaction(&self) -> bool {
787 matches!(
788 self.kind,
789 ConsensusTransactionKind::UserTransaction(_)
790 | ConsensusTransactionKind::UserTransactionV2(_)
791 )
792 }
793
794 pub fn is_user_transaction(&self) -> bool {
795 matches!(
796 self.kind,
797 ConsensusTransactionKind::UserTransaction(_)
798 | ConsensusTransactionKind::UserTransactionV2(_)
799 | ConsensusTransactionKind::CertifiedTransaction(_)
800 )
801 }
802
803 pub fn is_end_of_publish(&self) -> bool {
804 matches!(self.kind, ConsensusTransactionKind::EndOfPublish(_))
805 }
806}
807
808#[test]
809fn test_jwk_compatibility() {
810 let jwk = JWK {
815 kty: "a".to_string(),
816 e: "b".to_string(),
817 n: "c".to_string(),
818 alg: "d".to_string(),
819 };
820
821 let expected_jwk_bytes = vec![1, 97, 1, 98, 1, 99, 1, 100];
822 let jwk_bcs = bcs::to_bytes(&jwk).unwrap();
823 assert_eq!(jwk_bcs, expected_jwk_bytes);
824
825 let id = JwkId {
826 iss: "abc".to_string(),
827 kid: "def".to_string(),
828 };
829
830 let expected_id_bytes = vec![3, 97, 98, 99, 3, 100, 101, 102];
831 let id_bcs = bcs::to_bytes(&id).unwrap();
832 assert_eq!(id_bcs, expected_id_bytes);
833}