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