iota_verifier_latest/
struct_with_key_verifier.rs1use iota_types::{
11 IOTA_FRAMEWORK_ADDRESS,
12 error::ExecutionError,
13 fp_ensure,
14 id::{OBJECT_MODULE_NAME, UID_STRUCT_NAME},
15};
16use move_binary_format::file_format::{CompiledModule, SignatureToken};
17
18use crate::verification_failure;
19
20pub fn verify_module(module: &CompiledModule) -> Result<(), ExecutionError> {
21 verify_key_structs(module)?;
22 verify_no_key_enums(module)
23}
24
25fn verify_key_structs(module: &CompiledModule) -> Result<(), ExecutionError> {
26 let struct_defs = &module.struct_defs;
27 for def in struct_defs {
28 let handle = module.datatype_handle_at(def.struct_handle);
29 if !handle.abilities.has_key() {
30 continue;
31 }
32 let name = module.identifier_at(handle.name);
33
34 let first_field = match def.field(0) {
36 Some(field) => field,
37 None => {
38 return Err(verification_failure(format!(
39 "First field of struct {} must be 'id', no field found",
40 name
41 )));
42 }
43 };
44 let first_field_name = module.identifier_at(first_field.name).as_str();
45 if first_field_name != "id" {
46 return Err(verification_failure(format!(
47 "First field of struct {} must be 'id', {} found",
48 name, first_field_name
49 )));
50 }
51 let uid_field_type = &first_field.signature.0;
53 let uid_field_type = match uid_field_type {
54 SignatureToken::Datatype(struct_type) => struct_type,
55 _ => {
56 return Err(verification_failure(format!(
57 "First field of struct {} must be of type {}::object::UID, \
58 {:?} type found",
59 name, IOTA_FRAMEWORK_ADDRESS, uid_field_type
60 )));
61 }
62 };
63 let uid_type_struct = module.datatype_handle_at(*uid_field_type);
66 let uid_type_struct_name = module.identifier_at(uid_type_struct.name);
67 let uid_type_module = module.module_handle_at(uid_type_struct.module);
68 let uid_type_module_address = module.address_identifier_at(uid_type_module.address);
69 let uid_type_module_name = module.identifier_at(uid_type_module.name);
70 fp_ensure!(
71 uid_type_struct_name == UID_STRUCT_NAME
72 && uid_type_module_address == &IOTA_FRAMEWORK_ADDRESS
73 && uid_type_module_name == OBJECT_MODULE_NAME,
74 verification_failure(format!(
75 "First field of struct {} must be of type {}::object::UID, \
76 {}::{}::{} type found",
77 name,
78 IOTA_FRAMEWORK_ADDRESS,
79 uid_type_module_address,
80 uid_type_module_name,
81 uid_type_struct_name
82 ))
83 );
84 }
85 Ok(())
86}
87
88fn verify_no_key_enums(module: &CompiledModule) -> Result<(), ExecutionError> {
89 for def in &module.enum_defs {
90 let handle = module.datatype_handle_at(def.enum_handle);
91 if handle.abilities.has_key() {
92 return Err(verification_failure(format!(
93 "Enum {} cannot have the 'key' ability. Enums cannot have the 'key' ability.",
94 module.identifier_at(handle.name)
95 )));
96 }
97 }
98 Ok(())
99}