1#![cfg_attr(doc_cfg, feature(doc_cfg))]
109
110mod tree_display;
111pub(crate) use tree_display::{TreeDisplay, TreeWriter, impl_tree_display};
112
113#[cfg(feature = "hash")]
114#[cfg_attr(doc_cfg, doc(cfg(feature = "hash")))]
115pub mod hash;
116
117pub mod address;
118pub mod checkpoint;
119pub mod crypto;
120pub mod digest;
121pub mod effects;
122pub mod events;
123pub mod execution_status;
124pub mod framework;
125pub mod gas;
126pub mod iota_names;
127pub mod move_core;
128pub mod move_package;
129pub mod object;
130pub mod object_id;
131pub mod transaction;
132pub mod u256;
133pub mod utils;
134pub mod validator;
135pub mod version;
136
137pub use address::{Address, AddressParseError};
138pub use checkpoint::{
139 CheckpointCommitment, CheckpointContents, CheckpointContentsV1, CheckpointData,
140 CheckpointSequenceNumber, CheckpointSummary, CheckpointTimestamp, CheckpointTransaction,
141 CheckpointTransactionInfo, EndOfEpochData, EpochId, ProtocolVersion, SignedCheckpointSummary,
142 StakeUnit,
143};
144pub use crypto::{
145 Bls12381PublicKey, Bls12381Signature, Ed25519PublicKey, Ed25519Signature, HashingIntentScope,
146 INTENT_PREFIX_LENGTH, Intent, IntentAppId, IntentError, IntentMessage, IntentScope,
147 IntentVersion, InvalidSignatureScheme, MoveAuthenticator, MoveAuthenticatorV1,
148 MultisigAggregatedSignature, MultisigCommittee, MultisigMember, MultisigMemberSignature,
149 PasskeyAuthenticator, PasskeyPublicKey, PersonalMessage, PublicKey, PublicKeyError,
150 PublicKeyExt, Secp256k1PublicKey, Secp256k1Signature, Secp256r1PublicKey, Secp256r1Signature,
151 SignatureScheme, SimpleSignature, UserSignature,
152};
153pub use digest::{
154 CertificateDigest, CheckpointContentsDigest, CheckpointDigest, ConsensusCommitDigest, Digest,
155 DigestParseError, EffectsAuxDataDigest, MisbehaviorReportDigest, MoveAuthenticatorDigest,
156 ObjectDigest, SenderSignedDataDigest, SigningDigest, TransactionDigest,
157 TransactionEffectsDigest, TransactionEventsDigest,
158};
159pub use effects::{
160 ChangedObject, IdOperation, InputSharedObject, ObjectChange, ObjectIn, ObjectOut,
161 ObjectRemoveKind, TransactionEffects, TransactionEffectsV1, UnchangedSharedKind,
162 UnchangedSharedObject, WriteKind,
163};
164pub use events::{Event, TransactionEvents};
165pub use execution_status::{
166 CommandArgumentError, ExecutionError, ExecutionStatus, MoveLocation, PackageUpgradeError,
167 TypeArgumentError,
168};
169pub use framework::Coin;
170pub use gas::GasCostSummary;
171pub use move_core::{
172 Identifier, MAX_IDENTIFIER_LENGTH, MAX_TYPE_TAG_NESTING, StructTag, TypeParseError, TypeTag,
173};
174pub use move_package::{MovePackage, MovePackageData, TypeOrigin, UpgradeInfo, UpgradePolicy};
175pub use object::{
176 GenesisObject, MoveObjectType, MoveStruct, MoveStructContentsError, Object, ObjectData,
177 ObjectReference, ObjectType, ObjectVersion, OwnedObjectReference, Owner,
178};
179pub use object_id::ObjectId;
180#[cfg(feature = "serde")]
181#[cfg_attr(doc_cfg, doc(cfg(feature = "serde")))]
182pub(crate) use transaction::SignedTransactionWithIntentMessage;
183pub use transaction::{
184 Argument, CanceledTransaction, ChangeEpoch, ChangeEpochV2, ChangeEpochV3, ChangeEpochV4,
185 Command, ConsensusCommitPrologueV1, ConsensusDeterminedVersionAssignments, DenyRuleSet,
186 EndOfEpochTransactionKind, GasPayment, GenesisTransaction, Input, MakeMoveVector, MergeCoins,
187 MoveCall, ProgrammableTransaction, Publish, RandomnessRound, RandomnessStateUpdate,
188 SenderSignedTransaction, SharedObjectReference, SignedTransaction, SplitCoins, SystemPackage,
189 Transaction, TransactionDenyRulesUpdate, TransactionExpiration, TransactionKind, TransactionV1,
190 TransferObjects, Upgrade, VersionAssignment,
191};
192pub use validator::{
193 ValidatorAggregatedSignature, ValidatorCommittee, ValidatorCommitteeMember, ValidatorSignature,
194};
195pub use version::Version;
196
197#[cfg(all(test, feature = "serde", feature = "proptest"))]
198mod serialization_proptests;
199
200#[cfg(feature = "serde")]
201#[cfg_attr(doc_cfg, doc(cfg(feature = "serde")))]
202mod bcs_base64 {
203 use base64ct::Encoding;
204
205 macro_rules! impl_bcs_base64 {
206 ($($type:ident),* $(,)?) => {
207 $(
208 impl crate::$type {
209 paste::paste! {
210 #[doc = "Serialize this `" $type "` as a `Vec<u8>` of BCS bytes."]
211 pub fn to_bcs(&self) -> Vec<u8> {
212 bcs::to_bytes(self).expect("bcs serialization failed")
213 }
214
215 #[doc = "Serialize this `" $type "` as a base64-encoded string of its BCS bytes."]
216 pub fn to_base64(&self) -> String {
217 base64ct::Base64::encode_string(&self.to_bcs())
218 }
219
220 #[doc = "Deserialize a `" $type "` from BCS bytes."]
221 pub fn from_bcs(bytes: &[u8]) -> Result<Self, bcs::Error> {
222 bcs::from_bytes::<Self>(bytes)
223 }
224
225 #[doc = "Deserialize a `" $type "` from a base64-encoded string of its BCS bytes."]
226 pub fn from_base64(bytes: &str) -> Result<Self, bcs::Error> {
227 let decoded = base64ct::Base64::decode_vec(bytes)
228 .map_err(|e| bcs::Error::Custom(e.to_string()))?;
229 Self::from_bcs(&decoded)
230 }
231 }
232 }
233 )*
234 };
235 }
236
237 impl_bcs_base64!(
238 Object,
239 SenderSignedTransaction,
240 Transaction,
241 TransactionEffects,
242 TransactionKind,
243 TransactionV1,
244 );
245}
246
247pub const fn next_lexicographical_array<const N: usize>(array: &[u8; N]) -> [u8; N] {
249 match next_lexicographical_array_opt(array) {
250 Some(next) => next,
251 None => [0; N],
252 }
253}
254
255pub const fn next_lexicographical_array_opt<const N: usize>(array: &[u8; N]) -> Option<[u8; N]> {
258 let mut next = *array;
259 let mut i = N;
260
261 while i > 0 {
262 i -= 1;
263 let (new_byte, overflow) = next[i].overflowing_add(1);
264 next[i] = new_byte;
265
266 if !overflow {
267 return Some(next);
268 }
269 }
270
271 None
272}
273
274#[macro_export]
275macro_rules! def_is {
276 ($($variant:ident),* $(,)?) => {
277 paste::paste! {$(
278 #[doc = "Checks if this is a " $variant:snake " variant."]
279 #[inline]
280 pub fn [< is_ $variant:snake >](&self) -> bool {
281 matches!(self, Self::$variant { .. })
282 }
283 )*}
284 };
285}
286
287#[macro_export]
288macro_rules! def_is_as_into_opt {
289 (@into $variant:ident ($rename:ident) [Box<$inner:ty>]) => {
290 paste::paste! {
291 #[doc = "Converts this into a " $rename:snake " if it is a " $variant:snake " variant, or returns `None` otherwise."]
292 #[inline]
293 pub fn [< into_opt_ $rename >](self) -> Option<$inner> {
294 #[allow(irrefutable_let_patterns)]
295 if let Self::$variant(inner) = self {
296 Some(*inner)
297 } else {
298 None
299 }
300 }
301
302 #[doc = "Converts this into a " $rename:snake " if it is a " $variant:snake " variant, or panics otherwise."]
303 #[inline]
304 pub fn [< into_ $rename >](self) -> $inner {
305 self.[< into_opt_ $rename >]().expect(&format!("not a {}", stringify!($rename)))
306 }
307 }
308 };
309 (@into $variant:ident ($rename:ident) [$inner:ty]) => {
310 paste::paste! {
311 #[doc = "Converts this into a " $rename:snake " if it is a " $variant:snake " variant, or returns `None` otherwise."]
312 #[inline]
313 pub fn [< into_opt_ $rename >](self) -> Option<$inner> {
314 #[allow(irrefutable_let_patterns)]
315 if let Self::$variant(inner) = self {
316 Some(inner)
317 } else {
318 None
319 }
320 }
321
322 #[doc = "Converts this into a " $rename:snake " if it is a " $variant:snake " variant, or panics otherwise."]
323 #[inline]
324 pub fn [< into_ $rename >](self) -> $inner {
325 self.[< into_opt_ $rename >]().expect(&format!("not a {}", stringify!($variant)))
326 }
327 }
328 };
329 (@impl $variant:ident ($rename:ident) [Box<$inner:ty>]) => {
330 paste::paste! {
331 #[doc = "Checks if this is a " $rename:snake " variant."]
332 #[inline]
333 pub fn [< is_ $rename >](&self) -> bool {
334 matches!(self, Self::$variant(_))
335 }
336
337 #[doc = "Converts this into a " $rename:snake " if it is a " $variant:snake " variant, or panics otherwise."]
338 #[inline]
339 pub fn [< as_ $rename >](&self) -> &$inner {
340 self.[< as_opt_ $rename >]().expect(&format!("not a {}", stringify!($variant)))
341 }
342
343 #[doc = "Converts this into a " $rename:snake " if it is a " $variant:snake " variant, or returns `None` otherwise."]
344 #[inline]
345 pub fn [< as_opt_ $rename >](&self) -> Option<&$inner> {
346 #[allow(irrefutable_let_patterns)]
347 if let Self::$variant(inner) = self {
348 Some(inner)
349 } else {
350 None
351 }
352 }
353 }
354
355 $crate::def_is_as_into_opt!{@into $variant($rename) [Box<$inner>]}
356 };
357 (@impl $variant:ident ($rename:ident) [$inner:ty]) => {
358 paste::paste! {
359 #[doc = "Checks if this is a " $rename:snake " variant."]
360 #[inline]
361 pub fn [< is_ $rename >](&self) -> bool {
362 matches!(self, Self::$variant(_))
363 }
364
365 #[doc = "Converts this into a " $rename:snake " if it is a " $variant:snake " variant, or panics otherwise."]
366 #[inline]
367 pub fn [< as_ $rename >](&self) -> &$inner {
368 self.[< as_opt_ $rename >]().expect(&format!("not a {}", stringify!($variant)))
369 }
370
371 #[doc = "Converts this into a mut " $rename:snake " if it is a " $variant:snake " variant, or panics otherwise."]
372 #[inline]
373 pub fn [< as_mut_ $rename >](&mut self) -> &mut $inner {
374 self.[< as_opt_mut_ $rename >]().expect(&format!("not a {}", stringify!($variant)))
375 }
376
377 #[doc = "Converts this into a " $rename:snake " if it is a " $variant:snake " variant, or returns `None` otherwise."]
378 #[inline]
379 pub fn [< as_opt_ $rename >](&self) -> Option<&$inner> {
380 #[allow(irrefutable_let_patterns)]
381 if let Self::$variant(inner) = self {
382 Some(inner)
383 } else {
384 None
385 }
386 }
387
388 #[doc = "Converts this into a mut " $rename:snake " if it is a " $variant:snake " variant, or returns `None` otherwise."]
389 #[inline]
390 pub fn [< as_opt_mut_ $rename >](&mut self) -> Option<&mut $inner> {
391 #[allow(irrefutable_let_patterns)]
392 if let Self::$variant(inner) = self {
393 Some(inner)
394 } else {
395 None
396 }
397 }
398 }
399
400 $crate::def_is_as_into_opt!{@into $variant($rename) [$inner]}
401 };
402 (@parse $variant:ident ($rename:ident) [$($inner:tt)*]) => {
403 $crate::def_is_as_into_opt!{@impl $variant($rename) [$($inner)*]}
404 };
405 (@parse $variant:ident ($rename:ident)) => {
406 $crate::def_is_as_into_opt!{@impl $variant($rename) [$variant]}
407 };
408 (@parse $variant:ident [$($inner:tt)*]) => {
409 paste::paste! { $crate::def_is_as_into_opt!{@impl $variant ([< $variant:snake >]) [$($inner)*]} }
410 };
411 (@parse $variant:ident) => {
412 paste::paste! { $crate::def_is_as_into_opt!{@impl $variant ([< $variant:snake >]) [$variant]} }
413 };
414 ($($variant:ident $( as $rename:ident)? $(($($inner:tt)*))?),* $(,)?) => {
415 $(
416 $crate::def_is_as_into_opt!{@parse $variant $(($rename))? $([$($inner)*])?}
417 )*
418 };
419}
420
421#[cfg(feature = "serde")]
422mod _serde {
423 use std::borrow::Cow;
424
425 use base64ct::{Base64, Encoding};
426 use serde::{Deserialize, Deserializer, Serialize, Serializer};
427 use serde_with::{Bytes, DeserializeAs, SerializeAs};
428
429 pub(crate) type ReadableDisplay =
430 ::serde_with::As<::serde_with::IfIsHumanReadable<::serde_with::DisplayFromStr>>;
431
432 pub(crate) type OptionReadableDisplay =
433 ::serde_with::As<Option<::serde_with::IfIsHumanReadable<::serde_with::DisplayFromStr>>>;
434
435 pub(crate) type ReadableBase64Encoded =
436 ::serde_with::As<::serde_with::IfIsHumanReadable<Base64Encoded, ::serde_with::Bytes>>;
437
438 pub(crate) struct Base64Encoded;
439
440 impl<T: AsRef<[u8]>> SerializeAs<T> for Base64Encoded {
441 fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error>
442 where
443 S: Serializer,
444 {
445 let bytes = source.as_ref();
446 let b64 = Base64::encode_string(bytes);
447 b64.serialize(serializer)
448 }
449 }
450
451 impl<'de, T: TryFrom<Vec<u8>>> DeserializeAs<'de, T> for Base64Encoded {
452 fn deserialize_as<D>(deserializer: D) -> Result<T, D::Error>
453 where
454 D: Deserializer<'de>,
455 {
456 let b64: Cow<'de, str> = Deserialize::deserialize(deserializer)?;
457 let bytes = Base64::decode_vec(&b64).map_err(serde::de::Error::custom)?;
458 let length = bytes.len();
459 T::try_from(bytes).map_err(|_| {
460 serde::de::Error::custom(format_args!(
461 "Can't convert a Byte Vector of length {length} to the output type."
462 ))
463 })
464 }
465 }
466
467 pub(crate) struct BinaryRoaringBitmap;
470
471 impl SerializeAs<roaring::RoaringBitmap> for BinaryRoaringBitmap {
472 fn serialize_as<S>(
473 source: &roaring::RoaringBitmap,
474 serializer: S,
475 ) -> Result<S::Ok, S::Error>
476 where
477 S: Serializer,
478 {
479 let mut bytes = vec![];
480
481 source
482 .serialize_into(&mut bytes)
483 .map_err(serde::ser::Error::custom)?;
484 Bytes::serialize_as(&bytes, serializer)
485 }
486 }
487
488 impl<'de> DeserializeAs<'de, roaring::RoaringBitmap> for BinaryRoaringBitmap {
489 fn deserialize_as<D>(deserializer: D) -> Result<roaring::RoaringBitmap, D::Error>
490 where
491 D: Deserializer<'de>,
492 {
493 let bytes: Cow<'de, [u8]> = Bytes::deserialize_as(deserializer)?;
494 roaring::RoaringBitmap::deserialize_from(&bytes[..]).map_err(serde::de::Error::custom)
495 }
496 }
497
498 pub(crate) struct Base64RoaringBitmap;
499
500 impl SerializeAs<roaring::RoaringBitmap> for Base64RoaringBitmap {
501 fn serialize_as<S>(
502 source: &roaring::RoaringBitmap,
503 serializer: S,
504 ) -> Result<S::Ok, S::Error>
505 where
506 S: Serializer,
507 {
508 let mut bytes = vec![];
509
510 source
511 .serialize_into(&mut bytes)
512 .map_err(serde::ser::Error::custom)?;
513 let b64 = Base64::encode_string(&bytes);
514 b64.serialize(serializer)
515 }
516 }
517
518 impl<'de> DeserializeAs<'de, roaring::RoaringBitmap> for Base64RoaringBitmap {
519 fn deserialize_as<D>(deserializer: D) -> Result<roaring::RoaringBitmap, D::Error>
520 where
521 D: Deserializer<'de>,
522 {
523 let b64: Cow<'de, str> = Deserialize::deserialize(deserializer)?;
524 let bytes = Base64::decode_vec(&b64).map_err(serde::de::Error::custom)?;
525 roaring::RoaringBitmap::deserialize_from(&bytes[..]).map_err(serde::de::Error::custom)
526 }
527 }
528
529 pub(crate) use super::SignedTransactionWithIntentMessage;
530}
531
532#[cfg(test)]
533mod test {
534 use super::{next_lexicographical_array, next_lexicographical_array_opt};
535
536 #[test]
537 fn test_lexical_order() {
538 fn array_from_str(s: &str) -> [u8; 32] {
539 hex::decode(s).unwrap().try_into().unwrap()
540 }
541 assert_eq!(
542 next_lexicographical_array(&array_from_str(
543 "0000000000000000000000000000000000000000000000000000000000000000"
544 )),
545 array_from_str("0000000000000000000000000000000000000000000000000000000000000001"),
546 );
547 assert_eq!(
548 next_lexicographical_array(&array_from_str(
549 "000000000000000000000000000000000000000000000000000000000000ffff"
550 )),
551 array_from_str("0000000000000000000000000000000000000000000000000000000000010000"),
552 );
553 assert_eq!(
554 next_lexicographical_array(&array_from_str(
555 "000000000000000000000000000000000000000000000000000000000001002c"
556 )),
557 array_from_str("000000000000000000000000000000000000000000000000000000000001002d"),
558 );
559 assert_eq!(
560 next_lexicographical_array(&array_from_str(
561 "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
562 )),
563 array_from_str("0000000000000000000000000000000000000000000000000000000000000000"),
564 );
565 }
566
567 #[test]
568 fn test_lexical_order_opt() {
569 fn array_from_str(s: &str) -> [u8; 32] {
570 hex::decode(s).unwrap().try_into().unwrap()
571 }
572 assert_eq!(
573 next_lexicographical_array_opt(&array_from_str(
574 "0000000000000000000000000000000000000000000000000000000000000000"
575 )),
576 Some(array_from_str(
577 "0000000000000000000000000000000000000000000000000000000000000001"
578 )),
579 );
580 assert_eq!(
581 next_lexicographical_array_opt(&array_from_str(
582 "000000000000000000000000000000000000000000000000000000000000ffff"
583 )),
584 Some(array_from_str(
585 "0000000000000000000000000000000000000000000000000000000000010000"
586 )),
587 );
588 assert_eq!(
589 next_lexicographical_array_opt(&array_from_str(
590 "000000000000000000000000000000000000000000000000000000000001002c"
591 )),
592 Some(array_from_str(
593 "000000000000000000000000000000000000000000000000000000000001002d"
594 )),
595 );
596 assert_eq!(
597 next_lexicographical_array_opt(&array_from_str(
598 "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
599 )),
600 None,
601 );
602 }
603}