sui move deny_list

  • shaflow01
  • 更新于 2024-03-06 12:11
  • 阅读 913

引言dent_list是sui-framework实现的一个拒绝名单列表,用于进行对sui核心类型的地址访问控制。它仅能由系统事务创建,是shareobj,本文通过介绍deny_list的实现与使用,理解在suimove中实现访问控制的思想

引言

dent_list是sui-framework实现的一个拒绝名单列表,用于进行对sui核心类型的地址访问控制。它仅能由系统事务创建,是share obj,本文通过介绍deny_list的实现与使用,理解在sui move中实现访问控制的思想

deny_list

首先来看实现deny_list使用了哪些库

    use sui::table::{Self, Table};
    use sui::bag::{Self, Bag};
    use sui::vec_set::{Self, VecSet};

table、bag、vec_set在前面的文章都有分析

结构体

    struct DenyList has key {
        id: UID,

        lists: Bag,
    }

    struct PerTypeList has key, store {
        id: UID,

        denied_count: Table<address, u64>,

        denied_addresses: Table<vector<u8>, VecSet<address>>,
    }

拒绝名单的构成可以抽象为

                                     / address 1  
                              type 1    ...  
                            /        \ address n  
                TypeList 1      ...  
                            \        / address 1  
                              type n    ...  
                                     \ address n  
            /  
 DenyList         ...   
            \  
                                     / address 1  
                              type 1    ...  
                            /        \ address n  
                TypeList n      ...  
                            \        / address 1  
                              type n    ...  
                                     \ address n  

DenyList中bag:键为TypeList索引,值为相应的TypeList
TypeList中denied_count:用来快速检索一个地址是否在拒绝列表中
denied_addresses:用来储存拒绝列表 键为限制类型 用VecSet储存限制被限制的地址

添加/删除

    public(friend) fun add(
        deny_list: &mut DenyList,
        per_type_index: u64,
        type: vector<u8>,
        addr: address,
    ) {
        per_type_list_add(bag::borrow_mut(&mut deny_list.lists, per_type_index), type, addr)
    }

    fun per_type_list_add(
        list: &mut PerTypeList,
        type: vector<u8>,
        addr: address,
    ) {
        if (!table::contains(&list.denied_addresses, type)) {
            table::add(&mut list.denied_addresses, type, vec_set::empty());
        };
        let denied_addresses = table::borrow_mut(&mut list.denied_addresses, type);
        let already_denied = vec_set::contains(denied_addresses, &addr);
        if (already_denied) return;

        vec_set::insert(denied_addresses, addr);
        if (!table::contains(&list.denied_count, addr)) {
            table::add(&mut list.denied_count, addr, 0);
        };
        let denied_count = table::borrow_mut(&mut list.denied_count, addr);
        *denied_count = *denied_count + 1;
    }
  1. 先通过对应的per_type_index找到储存在DenyList中的对应TypeList
  2. 检查denied_addresses table中是否存在type类型的键 如果没有添加一个键为type类型的新的table
  3. 检查待添加的地址是否已经在拒绝列表中,如果存在直接返回
  4. 如果待添加地址还不存在 将其插入
  5. 检查此地址之前是否存在于拒绝列表,如果没有创建在denied_count table中添加相应的字段
  6. 将其denied_count加1
  public(friend) fun remove(
        deny_list: &mut DenyList,
        per_type_index: u64,
        type: vector<u8>,
        addr: address,
    ) {
        per_type_list_remove(bag::borrow_mut(&mut deny_list.lists, per_type_index), type, addr)
    }

    fun per_type_list_remove(
        list: &mut PerTypeList,
        type: vector<u8>,
        addr: address,
    ) {
        let denied_addresses = table::borrow_mut(&mut list.denied_addresses, type);
        assert!(vec_set::contains(denied_addresses, &addr), ENotDenied);
        vec_set::remove(denied_addresses, &addr);
        let denied_count = table::borrow_mut(&mut list.denied_count, addr);
        *denied_count = *denied_count - 1;
        if (*denied_count == 0) {
            table::remove(&mut list.denied_count, addr);
        }
    }
  1. 先通过对应的per_type_index找到储存在DenyList中的对应TypeList
  2. 根据type从denied_addresses table中取出相应的VecSet,检查待移除地址是否在其中
  3. 将denied_count table中对应地址的denied_count减去1
  4. 如果对应地址的denied_count成为0,说明他不存在于任任何拒绝名单中了,将其从denied_count table中移除

检验存在

    public(friend) fun contains(
        deny_list: &DenyList,
        per_type_index: u64,
        type: vector<u8>,
        addr: address,
    ): bool {
        per_type_list_contains(bag::borrow(&deny_list.lists, per_type_index), type, addr)
    }

    fun per_type_list_contains(
        list: &PerTypeList,
        type: vector<u8>,
        addr: address,
    ): bool {
        if (!table::contains(&list.denied_count, addr)) return false;

        let denied_count = table::borrow(&list.denied_count, addr);
        if (*denied_count == 0) return false;

        if (!table::contains(&list.denied_addresses, type)) return false;

        let denied_addresses = table::borrow(&list.denied_addresses, type);
        vec_set::contains(denied_addresses, &addr)
    }
  1. 先通过对应的per_type_index找到储存在DenyList中的对应TypeList
  2. 首先检查addr作为键是否存在于denied_count,如果没有,说明它不存在于任何type的拒绝列表中,返回false
  3. 再检查type作为键是否存在于denied_addresses table中,返回false
  4. 检查待检测addr是否存在于对应的VecSet中,存在返回true,否则返回false

总结

在本文中,介绍了sui-framework中的拒绝名单列表(deny_list)的实现与使用方法。该功能用于进行对sui核心类型的地址访问控制。希望有所帮助。

Move语言学习交流QQ群: 79489587 Sui官方中文开发者电报群: https://t.me/sui_dev_cn

  • 原创
  • 学分: 10
  • 分类: Move
  • 标签:
点赞 2
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
shaflow01
shaflow01
0x4937...bA76
江湖只有他的大名,没有他的介绍。