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