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_user_transaction_v2_message(
578 authority: &AuthorityName,
579 tx: PlainTransactionWithClaims,
580 ) -> Self {
581 let mut hasher = DefaultHasher::new();
582 let tx_digest = tx.tx().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::UserTransactionV2(Box::new(tx)),
589 }
590 }
591
592 pub fn new_checkpoint_signature_message_v2(data: CheckpointSignatureMessage) -> Self {
593 let mut hasher = DefaultHasher::new();
594 data.summary.auth_sig().signature.hash(&mut hasher);
595 let tracking_id = hasher.finish().to_le_bytes();
596 Self {
597 tracking_id,
598 kind: ConsensusTransactionKind::CheckpointSignatureV2(Box::new(data)),
599 }
600 }
601
602 pub fn new_end_of_publish(authority: AuthorityName) -> Self {
603 let mut hasher = DefaultHasher::new();
604 authority.hash(&mut hasher);
605 let tracking_id = hasher.finish().to_le_bytes();
606 Self {
607 tracking_id,
608 kind: ConsensusTransactionKind::EndOfPublish(authority),
609 }
610 }
611
612 pub fn new_capability_notification_v2(capabilities: AuthorityCapabilitiesV2) -> Self {
613 let mut hasher = DefaultHasher::new();
614 capabilities.hash(&mut hasher);
615 let tracking_id = hasher.finish().to_le_bytes();
616 Self {
617 tracking_id,
618 kind: ConsensusTransactionKind::CapabilityNotificationV2(capabilities),
619 }
620 }
621
622 pub fn new_mysticeti_certificate(
623 round: u64,
624 offset: u64,
625 certificate: CertifiedTransaction,
626 ) -> Self {
627 let mut hasher = DefaultHasher::new();
628 let tx_digest = certificate.digest();
629 tx_digest.hash(&mut hasher);
630 round.hash(&mut hasher);
631 offset.hash(&mut hasher);
632 let tracking_id = hasher.finish().to_le_bytes();
633 Self {
634 tracking_id,
635 kind: ConsensusTransactionKind::CertifiedTransaction(Box::new(certificate)),
636 }
637 }
638
639 pub fn new_jwk_fetched(authority: AuthorityName, id: JwkId, jwk: JWK) -> Self {
640 let mut hasher = DefaultHasher::new();
641 id.hash(&mut hasher);
642 let tracking_id = hasher.finish().to_le_bytes();
643 Self {
644 tracking_id,
645 kind: ConsensusTransactionKind::NewJWKFetched(authority, id, jwk),
646 }
647 }
648
649 pub fn new_randomness_dkg_message(
650 authority: AuthorityName,
651 versioned_message: &VersionedDkgMessage,
652 ) -> Self {
653 let message =
654 bcs::to_bytes(versioned_message).expect("message serialization should not fail");
655 let mut hasher = DefaultHasher::new();
656 message.hash(&mut hasher);
657 let tracking_id = hasher.finish().to_le_bytes();
658 Self {
659 tracking_id,
660 kind: ConsensusTransactionKind::RandomnessDkgMessage(authority, message),
661 }
662 }
663 pub fn new_randomness_dkg_confirmation(
664 authority: AuthorityName,
665 versioned_confirmation: &VersionedDkgConfirmation,
666 ) -> Self {
667 let confirmation =
668 bcs::to_bytes(versioned_confirmation).expect("message serialization should not fail");
669 let mut hasher = DefaultHasher::new();
670 confirmation.hash(&mut hasher);
671 let tracking_id = hasher.finish().to_le_bytes();
672 Self {
673 tracking_id,
674 kind: ConsensusTransactionKind::RandomnessDkgConfirmation(authority, confirmation),
675 }
676 }
677
678 pub fn new_execution_time_observation(observation: ExecutionTimeObservation) -> Self {
679 let mut hasher = DefaultHasher::new();
680 observation.hash(&mut hasher);
681 let tracking_id = hasher.finish().to_le_bytes();
682 Self {
683 tracking_id,
684 kind: ConsensusTransactionKind::ExecutionTimeObservation(observation),
685 }
686 }
687
688 pub fn get_tracking_id(&self) -> u64 {
689 (&self.tracking_id[..])
690 .read_u64::<BigEndian>()
691 .unwrap_or_default()
692 }
693
694 pub fn key(&self) -> ConsensusTransactionKey {
695 match &self.kind {
696 ConsensusTransactionKind::CertifiedTransaction(cert) => {
697 ConsensusTransactionKey::Certificate(*cert.digest())
698 }
699 ConsensusTransactionKind::CheckpointSignature(data) => {
700 ConsensusTransactionKey::CheckpointSignature(
701 data.summary.auth_sig().authority,
702 data.summary.sequence_number,
703 )
704 }
705 ConsensusTransactionKind::CheckpointSignatureV2(data) => {
706 ConsensusTransactionKey::CheckpointSignatureV2(
707 data.summary.auth_sig().authority,
708 data.summary.sequence_number,
709 *data.summary.digest(),
710 )
711 }
712 ConsensusTransactionKind::EndOfPublish(authority) => {
713 ConsensusTransactionKey::EndOfPublish(*authority)
714 }
715 ConsensusTransactionKind::CapabilityNotification(cap) => {
716 ConsensusTransactionKey::CapabilityNotification(cap.authority, cap.generation)
717 }
718 ConsensusTransactionKind::CapabilityNotificationV2(cap) => {
719 ConsensusTransactionKey::CapabilityNotification(cap.authority, cap.generation)
720 }
721 ConsensusTransactionKind::NewJWKFetched(authority, id, key) => {
722 ConsensusTransactionKey::NewJWKFetched(Box::new((
723 *authority,
724 id.clone(),
725 key.clone(),
726 )))
727 }
728 ConsensusTransactionKind::RandomnessStateUpdate(_, _) => {
729 debug_fatal!(
730 "there should never be a RandomnessStateUpdate with SequencedConsensusTransactionKind::External"
731 );
732 ConsensusTransactionKey::RandomnessStateUpdate
733 }
734 ConsensusTransactionKind::RandomnessDkgMessage(authority, _) => {
735 ConsensusTransactionKey::RandomnessDkgMessage(*authority)
736 }
737 ConsensusTransactionKind::RandomnessDkgConfirmation(authority, _) => {
738 ConsensusTransactionKey::RandomnessDkgConfirmation(*authority)
739 }
740 ConsensusTransactionKind::UserTransaction(tx) => {
741 ConsensusTransactionKey::Certificate(*tx.digest())
745 }
746 ConsensusTransactionKind::UserTransactionV2(tx) => {
747 ConsensusTransactionKey::Certificate(*tx.tx().digest())
751 }
752 ConsensusTransactionKind::ExecutionTimeObservation(msg) => {
753 ConsensusTransactionKey::ExecutionTimeObservation(msg.authority, msg.generation)
754 }
755 }
756 }
757
758 pub fn is_dkg(&self) -> bool {
759 matches!(
760 self.kind,
761 ConsensusTransactionKind::RandomnessDkgMessage(_, _)
762 | ConsensusTransactionKind::RandomnessDkgConfirmation(_, _)
763 )
764 }
765
766 pub fn is_user_transaction(&self) -> bool {
767 matches!(
769 self.kind,
770 ConsensusTransactionKind::UserTransaction(_)
771 | ConsensusTransactionKind::UserTransactionV2(_)
772 )
773 }
774
775 pub fn is_end_of_publish(&self) -> bool {
776 matches!(self.kind, ConsensusTransactionKind::EndOfPublish(_))
777 }
778}
779
780#[test]
781fn test_jwk_compatibility() {
782 let jwk = JWK {
787 kty: "a".to_string(),
788 e: "b".to_string(),
789 n: "c".to_string(),
790 alg: "d".to_string(),
791 };
792
793 let expected_jwk_bytes = vec![1, 97, 1, 98, 1, 99, 1, 100];
794 let jwk_bcs = bcs::to_bytes(&jwk).unwrap();
795 assert_eq!(jwk_bcs, expected_jwk_bytes);
796
797 let id = JwkId {
798 iss: "abc".to_string(),
799 kid: "def".to_string(),
800 };
801
802 let expected_id_bytes = vec![3, 97, 98, 99, 3, 100, 101, 102];
803 let id_bcs = bcs::to_bytes(&id).unwrap();
804 assert_eq!(id_bcs, expected_id_bytes);
805}