四、能力(Ability)

  • Ch1hiro
  • 更新于 5天前
  • 阅读 189

本篇文章学习四种能力,这在move语言中很重要

Sui_logo.png

1、能力 (Ability) 简介

1.1、能力 (Ability) 简介

​ 能力 (Abilities) 是 Move 独有的。拥有能力的类型才能和区块链进行交互。能力赋予指定类型操作的特殊注释,并通过控制类型的操作方式来帮助加强智能合约开发的安全性和正确性。

​ 能力 (Abilities) 是结构体声明和定义时即被赋予的。被赋予能力的实例将继承该能力。不是只有结构体才可被赋予能力,其它类型的实例也可以继承能力,只要该类型被赋予指定的能力。

has 是用于赋予类型能力 (Abilities) 的关键词。

1.2、Move 的四种能力

  1. copy:允许复制结构体的实例,即允许复制对象。Move 是面向资源管理的语言,像 Coin 之类的对象是不允许复制的(如同现实世界中你不允许通过复印现金来获取更多财富),因此需要使用 copy 能力来明确地指定哪些对象可以被复制。
  2. drop:允许删除或丢弃结构体的实例,拥有该能力的对象可以通过自动解构(析构)来实现删除的目的,而不需要我们手动删除。
  3. store:允许结构体的对象在全局存储中持久化,从而在多个交易之间共享和管理资源。并且可以作为其他对象的字段,从而创建复杂的数据结构。
  4. key:允许该结构体实例被全局存储和查找,拥有该能力的对象会有一个全局唯一的 ID 以便在 Sui 全局存储中进行查找和使用。

1.3、能力的功能

  1. 安全性:能力强制执行防止某些类型错误的规则,例如尝试复制无法复制的类型或存储无法持久的类型。
  2. 资源管理:通过指定能力,Move 可以确保对内存和存储等资源进行适当的管理,从而防止出现内存泄漏等问题。
  3. 访问控制:能力控制如何访问和操作类型,确保操作安全正确地执行。

同时,Move 的能力功能让智能合约回避了一些常见的问题:

  1. 不变性和持久性: storekey 管理与区块链全局存储交互的数据。没有 key 的类型将无法与区块链的全局存储交互,从而确保区块链状态的受控和安全操作。
  2. 资源安全: 智能合约通常涉及需要谨慎处理的资产和资源,以防止重复(双重支付)并确保正确清理。copydrop功能强制执行这些规则。

2、Copy 能力

在 Move 的语法,虽然原生类型可以自然的拥有 copy 和 drop 能力,但其它类型却必须明确地被指明它们的能力 (Abilities) 。

因为 Move 是为了表达数字资产和资源为设计的,不能任意复制是一个重要的特征。因此,Move 特地为此设计了 copy 能力。

⚠️ 注意:动态数组 (vector) 虽无需明确地指明它的能力,但它的类型 T必须具备特定操作所需的能力。

copy 能力语法格式如下:

<visibility modifier> <type> <name> has copy {}

在下面的例子中,被赋予 copy 能力后,hello 实例可以轻松地被复制,a 被复制到 b,然后使用解引用操作符复制到 c

1public struct hello has copy {}
2
3let a = hello {};
4let b = a;   // `a` 被复制到 `b`
5let c = *&b; 

3、Drop 能力

​ 我们一直强调 Move 是一个注重资源管理的语言,当一些实例不再被需要时,就需要清理,以腾出空间。这时, drop 就发挥作用了。这个小举动在一些普遍的语言是默认的,比如自动垃圾收集 (Automatic Garbage Collection),但 Move 则需要手动处理。如果没处理好,编译器可能会出现错误。这种处理资源的方法看似麻烦,但可以让程序员在编译时就发现问题,而不是在应用程序运行时才出现问题。这对于编辑去中心化应用 (DApp) 来说是很重要的。

drop 能力语法格式如下:

<visibility modifier> <type> <name> has drop {}

copy 一样,如果一个类型没被赋予 drop 能力,要访问就必须先解构。同样,要删除不再需要的实例时,没有 drop 能力的类型也需要先进行解构操作

⚠️ 注意: 不能任意 copy 资源是 Move 为了安全表达数字资产和资源为设计的。 而 drop 的设计让以不被需要的实例可以轻松删除。那么,如果要确定实例没有被无故删除,那么就不要给类型赋予 drop 能力。这样一来,就可以确保该资源会被处理妥当。

module hello::drop_ability {

    use std::string::{ utf8, String};

    public struct DropMe has drop {
        id: u8,
        name: String,
    }

    public struct NoDrop {}

    #[test]
    fun test_ignore() {
        // 创建 DropMe 结构的实例并自动忽略它。
        let _ = DropMe { id: 1, name: utf8(b"hello") };

        // 必须手动解构来忽略 no_drop 实例
        let no_drop = NoDrop {};                
        let NoDrop {} = no_drop;
    }
}

4、Key 能力

4.1、Key 能力

​ 在 Move 语言中,keystore 能力和区块链的全局存储有紧密相连。 key 主要用于标识类型在存储作为键 (key) 的功能。被赋予 key 能力的类型可以直接被用户,即 address 拥有。

4.2、对象定义

​ 在 Sui 中,key 能力必须与唯一标识符(UID)相结合使用,以确保资源的唯一性和可追踪性。UID 是一个全局唯一的标识符,用于标识特定的资源或对象。这也使拥有 key 的结构体类型被视为对象。

public struct MyObject has key, store {
    id: UID, // required
    name: String,
}

public fun new(name: String, ctx: &mut TxContext): MyObject {
    MyObject {
        id: object::new(ctx), 
        name,
    }
}

在这个例子中,MyObject 结构体包含一个 UID 字段,并具有 keystore 能力。UID 用于唯一标识每个对象,使其在全局存储中保持唯一性和安全性。

4.3、注意事项

  • 资源的销毁:具有 key 能力的资源在不再使用时应确保被正确销毁,以防止资源泄漏。
  • 全局存储限制:并非所有资源都需要 key 能力,只有那些需要存储在全局存储中的资源才需要具备此能力。
  • 权限管理:在使用 key 和 store 能力管理资源时,应注意权限控制,确保只有授权的实体能够访问和操作这些资源。

key 可以与 copy 和 drop 一起使用吗?

A:具有 key 能力的对象不能同时具有 copydrop 能力。原因如下:

  • copy 能力:允许对象被复制。对于具有 key 能力的对象来说,复制会破坏其唯一性,因此这两者是互斥的。
  • drop 能力:允许对象被丢弃。具有 key 能力的对象通常需要被精确管理和销毁(如 delete 操作),以防止资源泄漏和状态不一致,因此 drop 能力也是不允许的。

5、Store 能力

5.1、Store 能力

store 能力允许对象在全局存储中被持久化。store 能力与 key 能力常常结合使用,以确保对象既可以唯一标识又可以在全局存储中进行自由转移。拥有 store 能力的类型可以作为其他对象的字段,从而创建复杂的数据结构。

/// sui::Balance 结构体有 `store` 能力
public struct Balance<phantom T> has store {
    value: u64
}

/// sui::Coin 结构体具有 key + store 的能力,其中 Balance 以字段的形式包装在 Coin 中
public struct Coin<phantom T> has key, store {
    id: UID,
    balance: Balance<T>
}

​ 在这个例子中, Coin 同时拥有 keystore 的能力,它可以由其 owner 进行自由的转移,即我们常见的转账操作。而 Balance 具有 store 能力,它作为 Coin 的字段,同样存储在 Sui 的全局存储中。

具有 key key + store 能力的对象有什么区别?

A:只有 key 能力的对象:

  • 存储:可以存储在全局存储中。
  • 转移:不能被任意转移,需要特定的逻辑或权限来管理其全局存储中的位置,通常通过合约中定义的逻辑来实现转移操作。
  • 主要用途:标识唯一对象,如特定的用户账户或资源实例。

具有 key + store 能力的对象:

  • 存储:同样可以存储在全局存储中。
  • 转移:可以被 owner 自由转移和管理,这意味着可以在不同账户或合约之间流动。
  • 主要用途:需要频繁转移的资源,如代币、资产等。

具有 key 能力的对象如果没有 store 能力,就不能在全局存储中被自由转移,这样设计的目的是确保一些重要资源的稳定性和安全性。

点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
Ch1hiro
Ch1hiro
一名Web3爱好者