1#![warn(
6 future_incompatible,
7 nonstandard_style,
8 rust_2018_idioms,
9 rust_2021_compatibility
10)]
11
12#[cfg(not(target_arch = "wasm32"))]
13pub use iota_network_stack::multiaddr;
14use iota_sdk_types::Version;
15#[cfg(target_arch = "wasm32")]
16#[path = "wasm_multiaddr.rs"]
17pub mod multiaddr;
18pub use iota_sdk_types as sdk_types;
19use iota_sdk_types::{Address, ObjectId, StructTag, TypeTag};
20use move_binary_format::{
21 CompiledModule,
22 file_format::{AbilitySet, SignatureToken},
23};
24use move_bytecode_utils::resolve_struct;
25use move_core_types::{account_address::AccountAddress, language_storage::ModuleId};
26use object::OBJECT_START_VERSION;
27
28use crate::{
29 base_types::{RESOLVED_ASCII_STR, RESOLVED_STD_OPTION, RESOLVED_UTF8_STR},
30 id::RESOLVED_IOTA_ID,
31 iota_sdk_types_conversions::{struct_tag_core_to_sdk, type_tag_core_to_sdk},
32};
33
34#[macro_use]
35pub mod error;
36
37pub mod account_abstraction;
38pub mod auth_context;
39pub mod balance;
40pub mod base_types;
41pub mod clock;
42pub mod coin;
43pub mod coin_manager;
44pub mod collection_types;
45pub mod committee;
46pub mod config;
47pub mod crypto;
48pub mod deny_list_v1;
49pub mod deny_rule_governance;
50pub mod derived_object;
51pub mod digests;
52pub mod display;
53pub mod dynamic_field;
54pub mod effects;
55pub mod epoch_data;
56pub mod event;
57pub mod executable_transaction;
58pub mod execution;
59pub mod execution_config_utils;
60pub mod full_checkpoint_content;
61pub mod gas;
62pub mod gas_coin;
63pub mod gas_model;
64pub mod global_state_hash;
65pub mod governance;
66pub mod id;
67pub mod in_memory_storage;
68pub mod inner_temporary_store;
69pub mod iota_sdk_types_conversions;
70pub mod iota_serde;
71pub mod iota_system_state;
72pub mod layout_resolver;
73pub mod message_envelope;
74pub mod messages_checkpoint;
75#[cfg(not(target_arch = "wasm32"))]
78pub mod messages_consensus;
79#[cfg(not(target_arch = "wasm32"))]
80pub mod messages_grpc;
81pub mod messages_safe_client;
82pub mod metrics;
83pub mod mock_checkpoint_builder;
84pub mod move_authenticator;
85pub mod move_package;
86pub mod multisig;
87pub mod object;
88pub mod passkey_authenticator;
89pub mod programmable_transaction_builder;
90pub mod proto_value;
91pub mod quorum_driver_types;
92pub mod randomness_state;
93pub mod signature;
94pub mod signature_verification;
95pub mod stardust;
96pub mod storage;
97pub mod supported_protocol_versions;
98pub mod system_admin_cap;
99pub mod test_checkpoint_data_builder;
100pub mod timelock;
101pub mod traffic_control;
102pub mod transaction;
103pub mod transaction_driver_types;
104pub mod transaction_executor;
105pub mod transfer;
106pub mod versioned;
107
108#[path = "./unit_tests/utils.rs"]
109pub mod utils;
110
111macro_rules! built_in_ids {
112 ($($addr:ident / $id:ident = $init:expr);* $(;)?) => {
113 $(
114 pub const $addr: AccountAddress = builtin_address($init);
115 pub const $id: ObjectId = ObjectId::new($addr.into_bytes());
116 )*
117 }
118}
119
120macro_rules! built_in_pkgs {
121 ($($addr:ident / $id:ident = $init:expr);* $(;)?) => {
122 built_in_ids! { $($addr / $id = $init;)* }
123 }
124}
125
126built_in_pkgs! {
127 MOVE_STDLIB_ADDRESS / MOVE_STDLIB_PACKAGE_ID = 0x1;
128 IOTA_FRAMEWORK_ADDRESS / IOTA_FRAMEWORK_PACKAGE_ID = 0x2;
129 IOTA_SYSTEM_ADDRESS / IOTA_SYSTEM_PACKAGE_ID = 0x3;
130 GENESIS_BRIDGE_ADDRESS / GENESIS_BRIDGE_PACKAGE_ID = 0xb;
131 STARDUST_ADDRESS / STARDUST_PACKAGE_ID = 0x107a;
132}
133
134built_in_ids! {
135 IOTA_SYSTEM_STATE_ADDRESS / IOTA_SYSTEM_STATE_OBJECT_ID = 0x5;
136 IOTA_CLOCK_ADDRESS / IOTA_CLOCK_OBJECT_ID = 0x6;
137 IOTA_AUTHENTICATOR_STATE_ADDRESS / IOTA_AUTHENTICATOR_STATE_OBJECT_ID = 0x7;
138 IOTA_RANDOMNESS_STATE_ADDRESS / IOTA_RANDOMNESS_STATE_OBJECT_ID = 0x8;
139 GENESIS_IOTA_BRIDGE_ADDRESS / GENESIS_IOTA_BRIDGE_OBJECT_ID = 0x9;
140 IOTA_DENY_LIST_ADDRESS / IOTA_DENY_LIST_OBJECT_ID = 0x403;
141}
142
143pub const SYSTEM_PACKAGE_ADDRESSES: [Address; 5] = [
144 Address::STD,
145 Address::FRAMEWORK,
146 Address::SYSTEM,
147 Address::GENESIS_BRIDGE,
148 Address::STARDUST,
149];
150
151pub const IOTA_SYSTEM_STATE_OBJECT_SHARED_VERSION: Version = OBJECT_START_VERSION;
152pub const IOTA_CLOCK_OBJECT_SHARED_VERSION: Version = OBJECT_START_VERSION;
153
154const fn builtin_address(suffix: u16) -> AccountAddress {
155 let mut addr = [0u8; AccountAddress::LENGTH];
156 let [hi, lo] = suffix.to_be_bytes();
157 addr[AccountAddress::LENGTH - 2] = hi;
158 addr[AccountAddress::LENGTH - 1] = lo;
159 AccountAddress::new(addr)
160}
161
162pub fn iota_framework_address_concat_string(suffix: &str) -> String {
163 format!("{}{suffix}", Address::FRAMEWORK.to_short_hex())
164}
165
166pub fn parse_iota_address(s: &str) -> anyhow::Result<Address> {
177 use move_core_types::parsing::address::ParsedAddress;
178 Ok(Address::new(
179 ParsedAddress::parse(s)?
180 .into_account_address(&resolve_address)?
181 .into_bytes(),
182 ))
183}
184
185pub fn parse_iota_module_id(s: &str) -> anyhow::Result<ModuleId> {
190 use move_core_types::parsing::types::ParsedModuleId;
191 ParsedModuleId::parse(s)?.into_module_id(&resolve_address)
192}
193
194pub fn parse_iota_fq_name(s: &str) -> anyhow::Result<(ModuleId, String)> {
200 use move_core_types::parsing::types::ParsedFqName;
201 ParsedFqName::parse(s)?.into_fq_name(&resolve_address)
202}
203
204pub fn parse_iota_struct_tag(s: &str) -> anyhow::Result<StructTag> {
210 use move_core_types::parsing::types::ParsedStructType;
211 ParsedStructType::parse(s)?
212 .into_struct_tag(&resolve_address)
213 .map(|s| struct_tag_core_to_sdk(&s))
214}
215
216pub fn parse_iota_type_tag(s: &str) -> anyhow::Result<TypeTag> {
221 use move_core_types::parsing::types::ParsedType;
222 ParsedType::parse(s)?
223 .into_type_tag(&resolve_address)
224 .map(|s| type_tag_core_to_sdk(&s))
225}
226
227pub fn resolve_address(addr: &str) -> Option<AccountAddress> {
229 match addr {
230 "std" => Some(Address::STD),
231 "iota" => Some(Address::FRAMEWORK),
232 "iota_system" => Some(Address::SYSTEM),
233 "stardust" => Some(Address::STARDUST),
234 _ => None,
235 }
236 .map(|addr| AccountAddress::new(addr.into_bytes()))
237}
238
239pub trait MoveTypeTagTrait {
240 fn get_type_tag() -> TypeTag;
241}
242
243impl MoveTypeTagTrait for u8 {
244 fn get_type_tag() -> TypeTag {
245 TypeTag::U8
246 }
247}
248
249impl MoveTypeTagTrait for u64 {
250 fn get_type_tag() -> TypeTag {
251 TypeTag::U64
252 }
253}
254
255impl MoveTypeTagTrait for String {
256 fn get_type_tag() -> TypeTag {
257 TypeTag::Struct(Box::new(StructTag::new_string()))
258 }
259}
260
261impl MoveTypeTagTrait for ObjectId {
262 fn get_type_tag() -> TypeTag {
263 TypeTag::Address
264 }
265}
266
267impl MoveTypeTagTrait for Address {
268 fn get_type_tag() -> TypeTag {
269 TypeTag::Address
270 }
271}
272
273impl<T: MoveTypeTagTrait> MoveTypeTagTrait for Vec<T> {
274 fn get_type_tag() -> TypeTag {
275 TypeTag::Vector(Box::new(T::get_type_tag()))
276 }
277}
278
279pub fn is_primitive(
282 view: &CompiledModule,
283 function_type_args: &[AbilitySet],
284 s: &SignatureToken,
285) -> bool {
286 is_primitive_inner(view, function_type_args, s, false)
287}
288
289pub fn is_primitive_strict(
292 view: &CompiledModule,
293 function_type_args: &[AbilitySet],
294 s: &SignatureToken,
295) -> bool {
296 is_primitive_inner(view, function_type_args, s, true)
297}
298
299pub fn is_primitive_inner(
305 view: &CompiledModule,
306 function_type_args: &[AbilitySet],
307 s: &SignatureToken,
308 is_strict: bool,
309) -> bool {
310 use SignatureToken as S;
311 match s {
312 S::Bool | S::U8 | S::U16 | S::U32 | S::U64 | S::U128 | S::U256 | S::Address => true,
313 S::Signer => false,
314 S::TypeParameter(idx) => {
317 if !is_strict {
318 !function_type_args[*idx as usize].has_key()
320 } else {
321 let abilities = function_type_args[*idx as usize];
324 !abilities.has_key() && (abilities.has_copy() || abilities.has_drop())
325 }
326 }
327
328 S::Datatype(idx) => [RESOLVED_IOTA_ID, RESOLVED_ASCII_STR, RESOLVED_UTF8_STR]
329 .contains(&resolve_struct(view, *idx)),
330
331 S::DatatypeInstantiation(inst) => {
332 let (idx, targs) = &**inst;
333 let resolved_struct = resolve_struct(view, *idx);
334 resolved_struct == RESOLVED_STD_OPTION
336 && targs.len() == 1
337 && is_primitive_inner(view, function_type_args, &targs[0], is_strict)
338 }
339
340 S::Vector(inner) => is_primitive_inner(view, function_type_args, inner, is_strict),
341 S::Reference(_) | S::MutableReference(_) => false,
342 }
343}
344
345pub fn is_object(
346 view: &CompiledModule,
347 function_type_args: &[AbilitySet],
348 t: &SignatureToken,
349) -> Result<bool, String> {
350 use SignatureToken as S;
351 match t {
352 S::Reference(inner) | S::MutableReference(inner) => {
353 is_object(view, function_type_args, inner)
354 }
355 _ => is_object_struct(view, function_type_args, t),
356 }
357}
358
359pub fn is_object_vector(
360 view: &CompiledModule,
361 function_type_args: &[AbilitySet],
362 t: &SignatureToken,
363) -> Result<bool, String> {
364 use SignatureToken as S;
365 match t {
366 S::Vector(inner) => is_object_struct(view, function_type_args, inner),
367 _ => is_object_struct(view, function_type_args, t),
368 }
369}
370
371pub fn is_object_struct(
372 view: &CompiledModule,
373 function_type_args: &[AbilitySet],
374 s: &SignatureToken,
375) -> Result<bool, String> {
376 use SignatureToken as S;
377 match s {
378 S::Bool
379 | S::U8
380 | S::U16
381 | S::U32
382 | S::U64
383 | S::U128
384 | S::U256
385 | S::Address
386 | S::Signer
387 | S::Vector(_)
388 | S::Reference(_)
389 | S::MutableReference(_) => Ok(false),
390 S::TypeParameter(idx) => Ok(function_type_args
391 .get(*idx as usize)
392 .map(|abs| abs.has_key())
393 .unwrap_or(false)),
394 S::Datatype(_) | S::DatatypeInstantiation(_) => {
395 let abilities = view
396 .abilities(s, function_type_args)
397 .map_err(|vm_err| vm_err.to_string())?;
398 Ok(abilities.has_key())
399 }
400 }
401}
402
403#[cfg(test)]
404mod tests {
405 use expect_test::expect;
406
407 use super::*;
408
409 #[test]
410 fn test_parse_iota_numeric_address() {
411 let result = parse_iota_address("0x2").expect("should not error");
412
413 let expected =
414 expect!["0x0000000000000000000000000000000000000000000000000000000000000002"];
415 expected.assert_eq(&result.to_string());
416 }
417
418 #[test]
419 fn test_parse_iota_named_address() {
420 let result = parse_iota_address("iota").expect("should not error");
421
422 let expected =
423 expect!["0x0000000000000000000000000000000000000000000000000000000000000002"];
424 expected.assert_eq(&result.to_string());
425 }
426
427 #[test]
428 fn test_parse_iota_module_id() {
429 let result = parse_iota_module_id("0x2::iota").expect("should not error");
430 let expected =
431 expect!["0x0000000000000000000000000000000000000000000000000000000000000002::iota"];
432 expected.assert_eq(&result.to_canonical_string(true));
433 }
434
435 #[test]
436 fn test_parse_iota_fq_name() {
437 let (module, name) = parse_iota_fq_name("0x2::object::new").expect("should not error");
438 let expected = expect![
439 "0x0000000000000000000000000000000000000000000000000000000000000002::object::new"
440 ];
441 expected.assert_eq(&format!(
442 "{}::{name}",
443 module.to_canonical_display(true)
444 ));
445 }
446
447 #[test]
448 fn test_parse_iota_struct_tag_short_account_addr() {
449 let result = parse_iota_struct_tag("0x2::iota::IOTA").expect("should not error");
450
451 let expected = expect!["0x2::iota::IOTA"];
452 expected.assert_eq(&result.to_string());
453
454 let expected = expect![
455 "0x0000000000000000000000000000000000000000000000000000000000000002::iota::IOTA"
456 ];
457 expected.assert_eq(&result.to_canonical_string(true));
458 }
459
460 #[test]
461 fn test_parse_iota_struct_tag_long_account_addr() {
462 let result = parse_iota_struct_tag(
463 "0x0000000000000000000000000000000000000000000000000000000000000002::iota::IOTA",
464 )
465 .expect("should not error");
466
467 let expected = expect!["0x2::iota::IOTA"];
468 expected.assert_eq(&result.to_string());
469
470 let expected = expect![
471 "0x0000000000000000000000000000000000000000000000000000000000000002::iota::IOTA"
472 ];
473 expected.assert_eq(&result.to_canonical_string(true));
474 }
475
476 #[test]
477 fn test_parse_iota_struct_with_type_param_short_addr() {
478 let result =
479 parse_iota_struct_tag("0x2::coin::COIN<0x2::iota::IOTA>").expect("should not error");
480
481 let expected = expect!["0x2::coin::COIN<0x2::iota::IOTA>"];
482 expected.assert_eq(&result.to_string());
483
484 let expected = expect![
485 "0x0000000000000000000000000000000000000000000000000000000000000002::coin::COIN<0x0000000000000000000000000000000000000000000000000000000000000002::iota::IOTA>"
486 ];
487 expected.assert_eq(&result.to_canonical_string(true));
488 }
489
490 #[test]
491 fn test_parse_iota_struct_with_type_param_long_addr() {
492 let result = parse_iota_struct_tag("0x0000000000000000000000000000000000000000000000000000000000000002::coin::COIN<0x0000000000000000000000000000000000000000000000000000000000000002::iota::IOTA>")
493 .expect("should not error");
494
495 let expected = expect!["0x2::coin::COIN<0x2::iota::IOTA>"];
496 expected.assert_eq(&result.to_string());
497
498 let expected = expect![
499 "0x0000000000000000000000000000000000000000000000000000000000000002::coin::COIN<0x0000000000000000000000000000000000000000000000000000000000000002::iota::IOTA>"
500 ];
501 expected.assert_eq(&result.to_canonical_string(true));
502 }
503
504 #[test]
505 fn test_complex_struct_tag_with_short_addr() {
506 let result = parse_iota_struct_tag(
507 "0xe7::vec_coin::VecCoin<vector<0x2::coin::Coin<0x2::iota::IOTA>>>",
508 )
509 .expect("should not error");
510
511 let expected = expect!["0xe7::vec_coin::VecCoin<vector<0x2::coin::Coin<0x2::iota::IOTA>>>"];
512 expected.assert_eq(&result.to_string());
513
514 let expected = expect![
515 "0x00000000000000000000000000000000000000000000000000000000000000e7::vec_coin::VecCoin<vector<0x0000000000000000000000000000000000000000000000000000000000000002::coin::Coin<0x0000000000000000000000000000000000000000000000000000000000000002::iota::IOTA>>>"
516 ];
517 expected.assert_eq(&result.to_canonical_string(true));
518 }
519
520 #[test]
521 fn test_complex_struct_tag_with_long_addr() {
522 let result = parse_iota_struct_tag("0x00000000000000000000000000000000000000000000000000000000000000e7::vec_coin::VecCoin<vector<0x0000000000000000000000000000000000000000000000000000000000000002::coin::Coin<0x0000000000000000000000000000000000000000000000000000000000000002::iota::IOTA>>>")
523 .expect("should not error");
524
525 let expected = expect!["0xe7::vec_coin::VecCoin<vector<0x2::coin::Coin<0x2::iota::IOTA>>>"];
526 expected.assert_eq(&result.to_string());
527
528 let expected = expect![
529 "0x00000000000000000000000000000000000000000000000000000000000000e7::vec_coin::VecCoin<vector<0x0000000000000000000000000000000000000000000000000000000000000002::coin::Coin<0x0000000000000000000000000000000000000000000000000000000000000002::iota::IOTA>>>"
530 ];
531 expected.assert_eq(&result.to_canonical_string(true));
532 }
533
534 #[test]
535 fn test_dynamic_field_short_addr() {
536 let result = parse_iota_struct_tag(
537 "0x2::dynamic_field::Field<address, 0x2::balance::Balance<0x234::coin::COIN>>",
538 )
539 .expect("should not error");
540
541 let expected =
542 expect!["0x2::dynamic_field::Field<address, 0x2::balance::Balance<0x234::coin::COIN>>"];
543 expected.assert_eq(&result.to_string());
544
545 let expected = expect![
546 "0x0000000000000000000000000000000000000000000000000000000000000002::dynamic_field::Field<address,0x0000000000000000000000000000000000000000000000000000000000000002::balance::Balance<0x0000000000000000000000000000000000000000000000000000000000000234::coin::COIN>>"
547 ];
548 expected.assert_eq(&result.to_canonical_string(true));
549 }
550
551 #[test]
552 fn test_dynamic_field_long_addr() {
553 let result = parse_iota_struct_tag(
554 "0x2::dynamic_field::Field<address, 0x2::balance::Balance<0x234::coin::COIN>>",
555 )
556 .expect("should not error");
557
558 let expected =
559 expect!["0x2::dynamic_field::Field<address, 0x2::balance::Balance<0x234::coin::COIN>>"];
560 expected.assert_eq(&result.to_string());
561
562 let expected = expect![
563 "0x0000000000000000000000000000000000000000000000000000000000000002::dynamic_field::Field<address,0x0000000000000000000000000000000000000000000000000000000000000002::balance::Balance<0x0000000000000000000000000000000000000000000000000000000000000234::coin::COIN>>"
564 ];
565 expected.assert_eq(&result.to_canonical_string(true));
566 }
567}