sui_verifier_v1/
struct_with_key_verifier.rs

1// Copyright (c) Mysten Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4//! This pass verifies necessary properties for Move Objects, i.e. structs with the `key` ability.
5//! The properties checked are
6//! - The first field is named "id"
7//! - The first field has type `sui::object::UID`
8
9use crate::verification_failure;
10use move_binary_format::file_format::{CompiledModule, SignatureToken};
11use sui_types::{
12    error::ExecutionError,
13    fp_ensure,
14    id::{OBJECT_MODULE_NAME, UID_STRUCT_NAME},
15    SUI_FRAMEWORK_ADDRESS,
16};
17
18pub fn verify_module(module: &CompiledModule) -> Result<(), ExecutionError> {
19    verify_key_structs(module)
20}
21
22fn verify_key_structs(module: &CompiledModule) -> Result<(), ExecutionError> {
23    let struct_defs = &module.struct_defs;
24    for def in struct_defs {
25        let handle = module.datatype_handle_at(def.struct_handle);
26        if !handle.abilities.has_key() {
27            continue;
28        }
29        let name = module.identifier_at(handle.name);
30
31        // Check that the first field of the struct must be named "id".
32        let first_field = match def.field(0) {
33            Some(field) => field,
34            None => {
35                return Err(verification_failure(format!(
36                    "First field of struct {} must be 'id', no field found",
37                    name
38                )))
39            }
40        };
41        let first_field_name = module.identifier_at(first_field.name).as_str();
42        if first_field_name != "id" {
43            return Err(verification_failure(format!(
44                "First field of struct {} must be 'id', {} found",
45                name, first_field_name
46            )));
47        }
48        // Check that the "id" field must have a struct type.
49        let uid_field_type = &first_field.signature.0;
50        let uid_field_type = match uid_field_type {
51            SignatureToken::Datatype(struct_type) => struct_type,
52            _ => {
53                return Err(verification_failure(format!(
54                    "First field of struct {} must be of type {}::object::UID, \
55                    {:?} type found",
56                    name, SUI_FRAMEWORK_ADDRESS, uid_field_type
57                )))
58            }
59        };
60        // check that the struct type for "id" field must be SUI_FRAMEWORK_ADDRESS::object::UID.
61        let uid_type_struct = module.datatype_handle_at(*uid_field_type);
62        let uid_type_struct_name = module.identifier_at(uid_type_struct.name);
63        let uid_type_module = module.module_handle_at(uid_type_struct.module);
64        let uid_type_module_address = module.address_identifier_at(uid_type_module.address);
65        let uid_type_module_name = module.identifier_at(uid_type_module.name);
66        fp_ensure!(
67            uid_type_struct_name == UID_STRUCT_NAME
68                && uid_type_module_address == &SUI_FRAMEWORK_ADDRESS
69                && uid_type_module_name == OBJECT_MODULE_NAME,
70            verification_failure(format!(
71                "First field of struct {} must be of type {}::object::UID, \
72                {}::{}::{} type found",
73                name,
74                SUI_FRAMEWORK_ADDRESS,
75                uid_type_module_address,
76                uid_type_module_name,
77                uid_type_struct_name
78            ))
79        );
80    }
81    Ok(())
82}