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::UserTransactionV2(tx) => Some(tx.tx()),
474 _ => None,
475 }
476 }
477
478 pub fn into_user_transaction(self) -> Option<Transaction> {
479 match self {
480 ConsensusTransactionKind::UserTransactionV2(tx) => Some(tx.into_tx()),
481 _ => None,
482 }
483 }
484}
485
486#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
487#[allow(clippy::large_enum_variant)]
488pub enum VersionedDkgMessage {
489 V0(), V1(dkg_v1::Message<bls12381::G2Element, bls12381::G2Element>),
491}
492
493#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
494pub enum VersionedDkgConfirmation {
495 V0(), V1(dkg_v1::Confirmation<bls12381::G2Element>),
497}
498
499impl Debug for VersionedDkgMessage {
500 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
501 match self {
502 VersionedDkgMessage::V0() => write!(f, "Deprecated VersionedDkgMessage version 0"),
503 VersionedDkgMessage::V1(msg) => write!(
504 f,
505 "DKG V1 Message with sender={}, vss_pk.degree={}, encrypted_shares.len()={}",
506 msg.sender,
507 msg.vss_pk.degree(),
508 msg.encrypted_shares.len(),
509 ),
510 }
511 }
512}
513
514impl VersionedDkgMessage {
515 pub fn sender(&self) -> u16 {
516 match self {
517 VersionedDkgMessage::V0() => panic!("BUG: invalid VersionedDkgMessage version"),
518 VersionedDkgMessage::V1(msg) => msg.sender,
519 }
520 }
521
522 pub fn create(
523 dkg_version: u64,
524 party: Arc<dkg_v1::Party<bls12381::G2Element, bls12381::G2Element>>,
525 ) -> FastCryptoResult<VersionedDkgMessage> {
526 assert_eq!(dkg_version, 1, "BUG: invalid DKG version");
527 let msg = party.create_message(&mut rand::thread_rng())?;
528 Ok(VersionedDkgMessage::V1(msg))
529 }
530
531 pub fn unwrap_v1(self) -> dkg_v1::Message<bls12381::G2Element, bls12381::G2Element> {
532 match self {
533 VersionedDkgMessage::V1(msg) => msg,
534 _ => panic!("BUG: expected V1 message"),
535 }
536 }
537
538 pub fn is_valid_version(&self, dkg_version: u64) -> bool {
539 matches!((self, dkg_version), (VersionedDkgMessage::V1(_), 1))
540 }
541}
542
543impl VersionedDkgConfirmation {
544 pub fn sender(&self) -> u16 {
545 match self {
546 VersionedDkgConfirmation::V0() => {
547 panic!("BUG: invalid VersionedDkgConfirmation version")
548 }
549 VersionedDkgConfirmation::V1(msg) => msg.sender,
550 }
551 }
552
553 pub fn num_of_complaints(&self) -> usize {
554 match self {
555 VersionedDkgConfirmation::V0() => {
556 panic!("BUG: invalid VersionedDkgConfirmation version")
557 }
558 VersionedDkgConfirmation::V1(msg) => msg.complaints.len(),
559 }
560 }
561
562 pub fn unwrap_v1(&self) -> &dkg_v1::Confirmation<bls12381::G2Element> {
563 match self {
564 VersionedDkgConfirmation::V1(msg) => msg,
565 _ => panic!("BUG: expected V1 confirmation"),
566 }
567 }
568
569 pub fn is_valid_version(&self, dkg_version: u64) -> bool {
570 matches!((self, dkg_version), (VersionedDkgConfirmation::V1(_), 1))
571 }
572}
573
574impl ConsensusTransaction {
575 pub fn new_user_transaction_v2_message(
576 authority: &AuthorityName,
577 tx: PlainTransactionWithClaims,
578 ) -> Self {
579 let mut hasher = DefaultHasher::new();
580 let tx_digest = tx.tx().digest();
581 tx_digest.hash(&mut hasher);
582 authority.hash(&mut hasher);
583 let tracking_id = hasher.finish().to_le_bytes();
584 Self {
585 tracking_id,
586 kind: ConsensusTransactionKind::UserTransactionV2(Box::new(tx)),
587 }
588 }
589
590 pub fn new_checkpoint_signature_message_v2(data: CheckpointSignatureMessage) -> Self {
591 let mut hasher = DefaultHasher::new();
592 data.summary.auth_sig().signature.hash(&mut hasher);
593 let tracking_id = hasher.finish().to_le_bytes();
594 Self {
595 tracking_id,
596 kind: ConsensusTransactionKind::CheckpointSignatureV2(Box::new(data)),
597 }
598 }
599
600 pub fn new_end_of_publish(authority: AuthorityName) -> Self {
601 let mut hasher = DefaultHasher::new();
602 authority.hash(&mut hasher);
603 let tracking_id = hasher.finish().to_le_bytes();
604 Self {
605 tracking_id,
606 kind: ConsensusTransactionKind::EndOfPublish(authority),
607 }
608 }
609
610 pub fn new_capability_notification_v2(capabilities: AuthorityCapabilitiesV2) -> Self {
611 let mut hasher = DefaultHasher::new();
612 capabilities.hash(&mut hasher);
613 let tracking_id = hasher.finish().to_le_bytes();
614 Self {
615 tracking_id,
616 kind: ConsensusTransactionKind::CapabilityNotificationV2(capabilities),
617 }
618 }
619
620 pub fn new_jwk_fetched(authority: AuthorityName, id: JwkId, jwk: JWK) -> Self {
621 let mut hasher = DefaultHasher::new();
622 id.hash(&mut hasher);
623 let tracking_id = hasher.finish().to_le_bytes();
624 Self {
625 tracking_id,
626 kind: ConsensusTransactionKind::NewJWKFetched(authority, id, jwk),
627 }
628 }
629
630 pub fn new_randomness_dkg_message(
631 authority: AuthorityName,
632 versioned_message: &VersionedDkgMessage,
633 ) -> Self {
634 let message =
635 bcs::to_bytes(versioned_message).expect("message serialization should not fail");
636 let mut hasher = DefaultHasher::new();
637 message.hash(&mut hasher);
638 let tracking_id = hasher.finish().to_le_bytes();
639 Self {
640 tracking_id,
641 kind: ConsensusTransactionKind::RandomnessDkgMessage(authority, message),
642 }
643 }
644 pub fn new_randomness_dkg_confirmation(
645 authority: AuthorityName,
646 versioned_confirmation: &VersionedDkgConfirmation,
647 ) -> Self {
648 let confirmation =
649 bcs::to_bytes(versioned_confirmation).expect("message serialization should not fail");
650 let mut hasher = DefaultHasher::new();
651 confirmation.hash(&mut hasher);
652 let tracking_id = hasher.finish().to_le_bytes();
653 Self {
654 tracking_id,
655 kind: ConsensusTransactionKind::RandomnessDkgConfirmation(authority, confirmation),
656 }
657 }
658
659 pub fn new_execution_time_observation(observation: ExecutionTimeObservation) -> Self {
660 let mut hasher = DefaultHasher::new();
661 observation.hash(&mut hasher);
662 let tracking_id = hasher.finish().to_le_bytes();
663 Self {
664 tracking_id,
665 kind: ConsensusTransactionKind::ExecutionTimeObservation(observation),
666 }
667 }
668
669 pub fn get_tracking_id(&self) -> u64 {
670 (&self.tracking_id[..])
671 .read_u64::<BigEndian>()
672 .unwrap_or_default()
673 }
674
675 pub fn key(&self) -> ConsensusTransactionKey {
676 match &self.kind {
677 ConsensusTransactionKind::CertifiedTransaction(cert) => {
678 ConsensusTransactionKey::Certificate(*cert.digest())
679 }
680 ConsensusTransactionKind::CheckpointSignature(data) => {
681 ConsensusTransactionKey::CheckpointSignature(
682 data.summary.auth_sig().authority,
683 data.summary.sequence_number,
684 )
685 }
686 ConsensusTransactionKind::CheckpointSignatureV2(data) => {
687 ConsensusTransactionKey::CheckpointSignatureV2(
688 data.summary.auth_sig().authority,
689 data.summary.sequence_number,
690 *data.summary.digest(),
691 )
692 }
693 ConsensusTransactionKind::EndOfPublish(authority) => {
694 ConsensusTransactionKey::EndOfPublish(*authority)
695 }
696 ConsensusTransactionKind::CapabilityNotification(cap) => {
697 ConsensusTransactionKey::CapabilityNotification(cap.authority, cap.generation)
698 }
699 ConsensusTransactionKind::CapabilityNotificationV2(cap) => {
700 ConsensusTransactionKey::CapabilityNotification(cap.authority, cap.generation)
701 }
702 ConsensusTransactionKind::NewJWKFetched(authority, id, key) => {
703 ConsensusTransactionKey::NewJWKFetched(Box::new((
704 *authority,
705 id.clone(),
706 key.clone(),
707 )))
708 }
709 ConsensusTransactionKind::RandomnessStateUpdate(_, _) => {
710 debug_fatal!(
711 "there should never be a RandomnessStateUpdate with SequencedConsensusTransactionKind::External"
712 );
713 ConsensusTransactionKey::RandomnessStateUpdate
714 }
715 ConsensusTransactionKind::RandomnessDkgMessage(authority, _) => {
716 ConsensusTransactionKey::RandomnessDkgMessage(*authority)
717 }
718 ConsensusTransactionKind::RandomnessDkgConfirmation(authority, _) => {
719 ConsensusTransactionKey::RandomnessDkgConfirmation(*authority)
720 }
721 ConsensusTransactionKind::UserTransaction(tx) => {
722 ConsensusTransactionKey::Certificate(*tx.digest())
726 }
727 ConsensusTransactionKind::UserTransactionV2(tx) => {
728 ConsensusTransactionKey::Certificate(*tx.tx().digest())
732 }
733 ConsensusTransactionKind::ExecutionTimeObservation(msg) => {
734 ConsensusTransactionKey::ExecutionTimeObservation(msg.authority, msg.generation)
735 }
736 }
737 }
738
739 pub fn is_dkg(&self) -> bool {
740 matches!(
741 self.kind,
742 ConsensusTransactionKind::RandomnessDkgMessage(_, _)
743 | ConsensusTransactionKind::RandomnessDkgConfirmation(_, _)
744 )
745 }
746
747 pub fn is_user_transaction(&self) -> bool {
748 matches!(self.kind, ConsensusTransactionKind::UserTransactionV2(_))
750 }
751
752 pub fn is_end_of_publish(&self) -> bool {
753 matches!(self.kind, ConsensusTransactionKind::EndOfPublish(_))
754 }
755}
756
757#[test]
758fn test_jwk_compatibility() {
759 let jwk = JWK {
764 kty: "a".to_string(),
765 e: "b".to_string(),
766 n: "c".to_string(),
767 alg: "d".to_string(),
768 };
769
770 let expected_jwk_bytes = vec![1, 97, 1, 98, 1, 99, 1, 100];
771 let jwk_bcs = bcs::to_bytes(&jwk).unwrap();
772 assert_eq!(jwk_bcs, expected_jwk_bytes);
773
774 let id = JwkId {
775 iss: "abc".to_string(),
776 kid: "def".to_string(),
777 };
778
779 let expected_id_bytes = vec![3, 97, 98, 99, 3, 100, 101, 102];
780 let id_bcs = bcs::to_bytes(&id).unwrap();
781 assert_eq!(id_bcs, expected_id_bytes);
782}