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, 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)]
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 }
235 }
236}
237
238#[derive(Serialize, Deserialize, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
240pub enum ConsensusTransactionKey {
241 Certificate(TransactionDigest),
242 CheckpointSignature(AuthorityName, CheckpointSequenceNumber),
244 EndOfPublish(AuthorityName),
245 CapabilityNotification(AuthorityName, u64 ),
246 NewJWKFetched(Box<(AuthorityName, JwkId, JWK)>),
249 RandomnessDkgMessage(AuthorityName),
250 RandomnessDkgConfirmation(AuthorityName),
251 ExecutionTimeObservation(AuthorityName, u64 ),
252 CheckpointSignatureV2(AuthorityName, CheckpointSequenceNumber, CheckpointDigest),
254}
255
256impl Debug for ConsensusTransactionKey {
257 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
258 match self {
259 Self::Certificate(digest) => write!(f, "Certificate({:?})", digest),
260 Self::CheckpointSignature(name, seq) => {
261 write!(f, "CheckpointSignature({:?}, {:?})", name.concise(), seq)
262 }
263 Self::CheckpointSignatureV2(name, seq, digest) => write!(
264 f,
265 "CheckpointSignatureV2({:?}, {:?}, {:?})",
266 name.concise(),
267 seq,
268 digest
269 ),
270 Self::EndOfPublish(name) => write!(f, "EndOfPublish({:?})", name.concise()),
271 Self::CapabilityNotification(name, generation) => write!(
272 f,
273 "CapabilityNotification({:?}, {:?})",
274 name.concise(),
275 generation
276 ),
277 Self::NewJWKFetched(key) => {
278 let (authority, id, jwk) = &**key;
279 write!(
280 f,
281 "NewJWKFetched({:?}, {:?}, {:?})",
282 authority.concise(),
283 id,
284 jwk
285 )
286 }
287 Self::RandomnessDkgMessage(name) => {
288 write!(f, "RandomnessDkgMessage({:?})", name.concise())
289 }
290 Self::RandomnessDkgConfirmation(name) => {
291 write!(f, "RandomnessDkgConfirmation({:?})", name.concise())
292 }
293 Self::ExecutionTimeObservation(name, generation) => {
294 write!(
295 f,
296 "ExecutionTimeObservation({:?}, {generation:?})",
297 name.concise()
298 )
299 }
300 }
301 }
302}
303
304#[derive(Serialize, Deserialize, Clone, Hash)]
307pub struct AuthorityCapabilitiesV1 {
308 pub authority: AuthorityName,
310 pub generation: u64,
316
317 pub supported_protocol_versions: SupportedProtocolVersions,
319
320 pub available_system_packages: Vec<ObjectRef>,
323}
324
325impl Debug for AuthorityCapabilitiesV1 {
326 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
327 f.debug_struct("AuthorityCapabilities")
328 .field("authority", &self.authority.concise())
329 .field("generation", &self.generation)
330 .field(
331 "supported_protocol_versions",
332 &self.supported_protocol_versions,
333 )
334 .field("available_system_packages", &self.available_system_packages)
335 .finish()
336 }
337}
338
339impl AuthorityCapabilitiesV1 {
340 pub fn new(
341 authority: AuthorityName,
342 supported_protocol_versions: SupportedProtocolVersions,
343 available_system_packages: Vec<ObjectRef>,
344 ) -> Self {
345 let generation = SystemTime::now()
346 .duration_since(UNIX_EPOCH)
347 .expect("Sui did not exist prior to 1970")
348 .as_millis()
349 .try_into()
350 .expect("This build of sui is not supported in the year 500,000,000");
351 Self {
352 authority,
353 generation,
354 supported_protocol_versions,
355 available_system_packages,
356 }
357 }
358}
359
360#[derive(Serialize, Deserialize, Clone, Hash)]
363pub struct AuthorityCapabilitiesV2 {
364 pub authority: AuthorityName,
366 pub generation: u64,
372
373 pub supported_protocol_versions: SupportedProtocolVersionsWithHashes,
375
376 pub available_system_packages: Vec<ObjectRef>,
379}
380
381impl Debug for AuthorityCapabilitiesV2 {
382 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
383 f.debug_struct("AuthorityCapabilities")
384 .field("authority", &self.authority.concise())
385 .field("generation", &self.generation)
386 .field(
387 "supported_protocol_versions",
388 &self.supported_protocol_versions,
389 )
390 .field("available_system_packages", &self.available_system_packages)
391 .finish()
392 }
393}
394
395impl AuthorityCapabilitiesV2 {
396 pub fn new(
397 authority: AuthorityName,
398 chain: Chain,
399 supported_protocol_versions: SupportedProtocolVersions,
400 available_system_packages: Vec<ObjectRef>,
401 ) -> Self {
402 let generation = SystemTime::now()
403 .duration_since(UNIX_EPOCH)
404 .expect("Sui did not exist prior to 1970")
405 .as_millis()
406 .try_into()
407 .expect("This build of sui is not supported in the year 500,000,000");
408 Self {
409 authority,
410 generation,
411 supported_protocol_versions:
412 SupportedProtocolVersionsWithHashes::from_supported_versions(
413 supported_protocol_versions,
414 chain,
415 ),
416 available_system_packages,
417 }
418 }
419}
420
421#[derive(Debug, Default, PartialEq, Eq, Hash, Clone, Serialize, Deserialize)]
424pub struct ExecutionTimeObservation {
425 pub authority: AuthorityName,
427 pub generation: u64,
430
431 pub estimates: Vec<(ExecutionTimeObservationKey, Duration)>,
433}
434
435impl ExecutionTimeObservation {
436 pub fn new(
437 authority: AuthorityName,
438 generation: u64,
439 estimates: Vec<(ExecutionTimeObservationKey, Duration)>,
440 ) -> Self {
441 Self {
442 authority,
443 generation,
444 estimates,
445 }
446 }
447}
448
449#[derive(Serialize, Deserialize, Clone, Debug)]
450pub enum ConsensusTransactionKind {
451 CertifiedTransaction(Box<CertifiedTransaction>),
452 CheckpointSignature(Box<CheckpointSignatureMessage>),
454 EndOfPublish(AuthorityName),
455
456 CapabilityNotification(AuthorityCapabilitiesV1),
457
458 NewJWKFetched(AuthorityName, JwkId, JWK),
459 RandomnessStateUpdate(u64, Vec<u8>), RandomnessDkgMessage(AuthorityName, Vec<u8>),
464 RandomnessDkgConfirmation(AuthorityName, Vec<u8>),
468
469 CapabilityNotificationV2(AuthorityCapabilitiesV2),
470
471 UserTransaction(Box<Transaction>),
472
473 ExecutionTimeObservation(ExecutionTimeObservation),
474 CheckpointSignatureV2(Box<CheckpointSignatureMessage>),
476}
477
478impl ConsensusTransactionKind {}
479
480#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
481#[allow(clippy::large_enum_variant)]
482pub enum VersionedDkgMessage {
483 V0(), V1(dkg_v1::Message<bls12381::G2Element, bls12381::G2Element>),
485}
486
487#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
488pub enum VersionedDkgConfirmation {
489 V0(), V1(dkg_v1::Confirmation<bls12381::G2Element>),
491}
492
493impl Debug for VersionedDkgMessage {
494 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
495 match self {
496 VersionedDkgMessage::V0() => write!(f, "Deprecated VersionedDkgMessage version 0"),
497 VersionedDkgMessage::V1(msg) => write!(
498 f,
499 "DKG V1 Message with sender={}, vss_pk.degree={}, encrypted_shares.len()={}",
500 msg.sender,
501 msg.vss_pk.degree(),
502 msg.encrypted_shares.len(),
503 ),
504 }
505 }
506}
507
508impl VersionedDkgMessage {
509 pub fn sender(&self) -> u16 {
510 match self {
511 VersionedDkgMessage::V0() => panic!("BUG: invalid VersionedDkgMessage version"),
512 VersionedDkgMessage::V1(msg) => msg.sender,
513 }
514 }
515
516 pub fn create(
517 dkg_version: u64,
518 party: Arc<dkg_v1::Party<bls12381::G2Element, bls12381::G2Element>>,
519 ) -> FastCryptoResult<VersionedDkgMessage> {
520 assert_eq!(dkg_version, 1, "BUG: invalid DKG version");
521 let msg = party.create_message(&mut rand::thread_rng())?;
522 Ok(VersionedDkgMessage::V1(msg))
523 }
524
525 pub fn unwrap_v1(self) -> dkg_v1::Message<bls12381::G2Element, bls12381::G2Element> {
526 match self {
527 VersionedDkgMessage::V1(msg) => msg,
528 _ => panic!("BUG: expected V1 message"),
529 }
530 }
531
532 pub fn is_valid_version(&self, dkg_version: u64) -> bool {
533 matches!((self, dkg_version), (VersionedDkgMessage::V1(_), 1))
534 }
535}
536
537impl VersionedDkgConfirmation {
538 pub fn sender(&self) -> u16 {
539 match self {
540 VersionedDkgConfirmation::V0() => {
541 panic!("BUG: invalid VersionedDkgConfirmation version")
542 }
543 VersionedDkgConfirmation::V1(msg) => msg.sender,
544 }
545 }
546
547 pub fn num_of_complaints(&self) -> usize {
548 match self {
549 VersionedDkgConfirmation::V0() => {
550 panic!("BUG: invalid VersionedDkgConfirmation version")
551 }
552 VersionedDkgConfirmation::V1(msg) => msg.complaints.len(),
553 }
554 }
555
556 pub fn unwrap_v1(&self) -> &dkg_v1::Confirmation<bls12381::G2Element> {
557 match self {
558 VersionedDkgConfirmation::V1(msg) => msg,
559 _ => panic!("BUG: expected V1 confirmation"),
560 }
561 }
562
563 pub fn is_valid_version(&self, dkg_version: u64) -> bool {
564 matches!((self, dkg_version), (VersionedDkgConfirmation::V1(_), 1))
565 }
566}
567
568impl ConsensusTransaction {
569 pub fn new_certificate_message(
570 authority: &AuthorityName,
571 certificate: CertifiedTransaction,
572 ) -> Self {
573 let mut hasher = DefaultHasher::new();
574 let tx_digest = certificate.digest();
575 tx_digest.hash(&mut hasher);
576 authority.hash(&mut hasher);
577 let tracking_id = hasher.finish().to_le_bytes();
578 Self {
579 tracking_id,
580 kind: ConsensusTransactionKind::CertifiedTransaction(Box::new(certificate)),
581 }
582 }
583
584 pub fn new_user_transaction_message(authority: &AuthorityName, tx: Transaction) -> Self {
585 let mut hasher = DefaultHasher::new();
586 let tx_digest = tx.digest();
587 tx_digest.hash(&mut hasher);
588 authority.hash(&mut hasher);
589 let tracking_id = hasher.finish().to_le_bytes();
590 Self {
591 tracking_id,
592 kind: ConsensusTransactionKind::UserTransaction(Box::new(tx)),
593 }
594 }
595
596 pub fn new_checkpoint_signature_message(data: CheckpointSignatureMessage) -> Self {
597 let mut hasher = DefaultHasher::new();
598 data.summary.auth_sig().signature.hash(&mut hasher);
599 let tracking_id = hasher.finish().to_le_bytes();
600 Self {
601 tracking_id,
602 kind: ConsensusTransactionKind::CheckpointSignature(Box::new(data)),
603 }
604 }
605
606 pub fn new_checkpoint_signature_message_v2(data: CheckpointSignatureMessage) -> Self {
607 let mut hasher = DefaultHasher::new();
608 data.summary.auth_sig().signature.hash(&mut hasher);
609 let tracking_id = hasher.finish().to_le_bytes();
610 Self {
611 tracking_id,
612 kind: ConsensusTransactionKind::CheckpointSignatureV2(Box::new(data)),
613 }
614 }
615
616 pub fn new_end_of_publish(authority: AuthorityName) -> Self {
617 let mut hasher = DefaultHasher::new();
618 authority.hash(&mut hasher);
619 let tracking_id = hasher.finish().to_le_bytes();
620 Self {
621 tracking_id,
622 kind: ConsensusTransactionKind::EndOfPublish(authority),
623 }
624 }
625
626 pub fn new_capability_notification(capabilities: AuthorityCapabilitiesV1) -> Self {
627 let mut hasher = DefaultHasher::new();
628 capabilities.hash(&mut hasher);
629 let tracking_id = hasher.finish().to_le_bytes();
630 Self {
631 tracking_id,
632 kind: ConsensusTransactionKind::CapabilityNotification(capabilities),
633 }
634 }
635
636 pub fn new_capability_notification_v2(capabilities: AuthorityCapabilitiesV2) -> Self {
637 let mut hasher = DefaultHasher::new();
638 capabilities.hash(&mut hasher);
639 let tracking_id = hasher.finish().to_le_bytes();
640 Self {
641 tracking_id,
642 kind: ConsensusTransactionKind::CapabilityNotificationV2(capabilities),
643 }
644 }
645
646 pub fn new_mysticeti_certificate(
647 round: u64,
648 offset: u64,
649 certificate: CertifiedTransaction,
650 ) -> Self {
651 let mut hasher = DefaultHasher::new();
652 let tx_digest = certificate.digest();
653 tx_digest.hash(&mut hasher);
654 round.hash(&mut hasher);
655 offset.hash(&mut hasher);
656 let tracking_id = hasher.finish().to_le_bytes();
657 Self {
658 tracking_id,
659 kind: ConsensusTransactionKind::CertifiedTransaction(Box::new(certificate)),
660 }
661 }
662
663 pub fn new_jwk_fetched(authority: AuthorityName, id: JwkId, jwk: JWK) -> Self {
664 let mut hasher = DefaultHasher::new();
665 id.hash(&mut hasher);
666 let tracking_id = hasher.finish().to_le_bytes();
667 Self {
668 tracking_id,
669 kind: ConsensusTransactionKind::NewJWKFetched(authority, id, jwk),
670 }
671 }
672
673 pub fn new_randomness_dkg_message(
674 authority: AuthorityName,
675 versioned_message: &VersionedDkgMessage,
676 ) -> Self {
677 let message =
678 bcs::to_bytes(versioned_message).expect("message serialization should not fail");
679 let mut hasher = DefaultHasher::new();
680 message.hash(&mut hasher);
681 let tracking_id = hasher.finish().to_le_bytes();
682 Self {
683 tracking_id,
684 kind: ConsensusTransactionKind::RandomnessDkgMessage(authority, message),
685 }
686 }
687 pub fn new_randomness_dkg_confirmation(
688 authority: AuthorityName,
689 versioned_confirmation: &VersionedDkgConfirmation,
690 ) -> Self {
691 let confirmation =
692 bcs::to_bytes(versioned_confirmation).expect("message serialization should not fail");
693 let mut hasher = DefaultHasher::new();
694 confirmation.hash(&mut hasher);
695 let tracking_id = hasher.finish().to_le_bytes();
696 Self {
697 tracking_id,
698 kind: ConsensusTransactionKind::RandomnessDkgConfirmation(authority, confirmation),
699 }
700 }
701
702 pub fn new_execution_time_observation(observation: ExecutionTimeObservation) -> Self {
703 let mut hasher = DefaultHasher::new();
704 observation.hash(&mut hasher);
705 let tracking_id = hasher.finish().to_le_bytes();
706 Self {
707 tracking_id,
708 kind: ConsensusTransactionKind::ExecutionTimeObservation(observation),
709 }
710 }
711
712 pub fn get_tracking_id(&self) -> u64 {
713 (&self.tracking_id[..])
714 .read_u64::<BigEndian>()
715 .unwrap_or_default()
716 }
717
718 pub fn key(&self) -> ConsensusTransactionKey {
719 match &self.kind {
720 ConsensusTransactionKind::CertifiedTransaction(cert) => {
721 ConsensusTransactionKey::Certificate(*cert.digest())
722 }
723 ConsensusTransactionKind::CheckpointSignature(data) => {
724 ConsensusTransactionKey::CheckpointSignature(
725 data.summary.auth_sig().authority,
726 data.summary.sequence_number,
727 )
728 }
729 ConsensusTransactionKind::CheckpointSignatureV2(data) => {
730 ConsensusTransactionKey::CheckpointSignatureV2(
731 data.summary.auth_sig().authority,
732 data.summary.sequence_number,
733 *data.summary.digest(),
734 )
735 }
736 ConsensusTransactionKind::EndOfPublish(authority) => {
737 ConsensusTransactionKey::EndOfPublish(*authority)
738 }
739 ConsensusTransactionKind::CapabilityNotification(cap) => {
740 ConsensusTransactionKey::CapabilityNotification(cap.authority, cap.generation)
741 }
742 ConsensusTransactionKind::CapabilityNotificationV2(cap) => {
743 ConsensusTransactionKey::CapabilityNotification(cap.authority, cap.generation)
744 }
745 ConsensusTransactionKind::NewJWKFetched(authority, id, key) => {
746 ConsensusTransactionKey::NewJWKFetched(Box::new((
747 *authority,
748 id.clone(),
749 key.clone(),
750 )))
751 }
752 ConsensusTransactionKind::RandomnessStateUpdate(_, _) => {
753 unreachable!(
754 "there should never be a RandomnessStateUpdate with SequencedConsensusTransactionKind::External"
755 )
756 }
757 ConsensusTransactionKind::RandomnessDkgMessage(authority, _) => {
758 ConsensusTransactionKey::RandomnessDkgMessage(*authority)
759 }
760 ConsensusTransactionKind::RandomnessDkgConfirmation(authority, _) => {
761 ConsensusTransactionKey::RandomnessDkgConfirmation(*authority)
762 }
763 ConsensusTransactionKind::UserTransaction(tx) => {
764 ConsensusTransactionKey::Certificate(*tx.digest())
768 }
769 ConsensusTransactionKind::ExecutionTimeObservation(msg) => {
770 ConsensusTransactionKey::ExecutionTimeObservation(msg.authority, msg.generation)
771 }
772 }
773 }
774
775 pub fn is_dkg(&self) -> bool {
776 matches!(
777 self.kind,
778 ConsensusTransactionKind::RandomnessDkgMessage(_, _)
779 | ConsensusTransactionKind::RandomnessDkgConfirmation(_, _)
780 )
781 }
782
783 pub fn is_mfp_transaction(&self) -> bool {
784 matches!(self.kind, ConsensusTransactionKind::UserTransaction(_))
785 }
786
787 pub fn is_user_transaction(&self) -> bool {
788 matches!(
789 self.kind,
790 ConsensusTransactionKind::UserTransaction(_)
791 | ConsensusTransactionKind::CertifiedTransaction(_)
792 )
793 }
794
795 pub fn is_end_of_publish(&self) -> bool {
796 matches!(self.kind, ConsensusTransactionKind::EndOfPublish(_))
797 }
798}
799
800#[test]
801fn test_jwk_compatibility() {
802 let jwk = JWK {
807 kty: "a".to_string(),
808 e: "b".to_string(),
809 n: "c".to_string(),
810 alg: "d".to_string(),
811 };
812
813 let expected_jwk_bytes = vec![1, 97, 1, 98, 1, 99, 1, 100];
814 let jwk_bcs = bcs::to_bytes(&jwk).unwrap();
815 assert_eq!(jwk_bcs, expected_jwk_bytes);
816
817 let id = JwkId {
818 iss: "abc".to_string(),
819 kid: "def".to_string(),
820 };
821
822 let expected_id_bytes = vec![3, 97, 98, 99, 3, 100, 101, 102];
823 let id_bcs = bcs::to_bytes(&id).unwrap();
824 assert_eq!(id_bcs, expected_id_bytes);
825}