Sui Move 学习:Object & 四种能力

  • EGAL
  • 更新于 1天前
  • 阅读 176

Siu是如何处理资产所有权在Sui上,Object是数据储存的基本单位,通过定义,创建和管理这些代表用户资产级的可编程对象。Objecttype(对象类型)Sui定义的每个对象都会用有key和UID。在区块链浏览器查看,可以看到五个基本参数—owner,objectId,ty

Siu 是如何处理资产所有权

在Sui上,Object是数据储存的基本单位,通过定义,创建和管理这些代表用户资产级的可编程对象。

Object type (对象类型)

Sui 定义的每个对象都会用有key 和 UID。在区块链浏览器查看,可以看到五个基本参数 — owner,objectId, type, version, 最后一个交易摘要。 我们还可以通过其他字段来定义object 完善功能。

Object ownership (对象所有权)

Sui链上的,每个对象都有一个owner字段,它决定了对象在事务中的使用方式。

Address-owned (地址所有)

地址所有对象限制了访问权限,只有对应地址的所有者才能对其进行操作。

public fun transfer<T: key>(obj: T, recipient: address)

public fun public_transfer<T: key + store>(obj: T, recipient: address)

Dynamic fields  (动态字段)

Sui的动态字段和对象是动态添加和删除的,动态字段允许我们根据需要调整对象的机构,按需消耗gas。

Fields 可以存储任务课存储的值,Object Fields 只能存具有 key 能力的对象

Immutable 不可变

不能被更改,转移活着删除,这类对象没有所有者,可以被任何人使用。

Shared  共享

0x2::transfer::share_object

共享对象需要 key 能力,可被公开访问和使用。

下面例子是创建一个销售甜甜圈的商店,每个人都需要访问商店菜才能购买。

module examples::donuts {
    use sui::transfer;
    use sui::sui::SUI;
    use sui::coin::{Self, Coin};
    use sui::object::{Self, UID};
    use sui::balance::{Self, Balance};
    use sui::tx_context::{Self, TxContext};

    /// For when Coin balance is too low.
    const ENotEnough: u64 = 0;

    /// Capability that grants an owner the right to collect profits.
    struct ShopOwnerCap has key { id: UID }

    /// A purchasable Donut. For simplicity's sake we ignore implementation.
    struct Donut has key { id: UID }

    /// A shared object. `key` ability is required.
    struct DonutShop has key {
        id: UID,
        price: u64,
        balance: Balance<SUI>
    }

    /// Init function is often ideal place for initializing
    /// a shared object as it is called only once.
    fun init(ctx: &mut TxContext) {
        transfer::transfer(ShopOwnerCap {
            id: object::new(ctx)
        }, tx_context::sender(ctx));

        // Share the object to make it accessible to everyone!
        transfer::share_object(DonutShop {
            id: object::new(ctx),
            price: 1000,
            balance: balance::zero()
        })
    }

    /// Entry function available to everyone who owns a Coin.
    public fun buy_donut(
        shop: &mut DonutShop, payment: &mut Coin<SUI>, ctx: &mut TxContext
    ) {
        assert!(coin::value(payment) >= shop.price, ENotEnough);

        // Take amount = `shop.price` from Coin<SUI>
        let coin_balance = coin::balance_mut(payment);
        let paid = balance::split(coin_balance, shop.price);

        // Put the coin to the Shop's balance
        balance::join(&mut shop.balance, paid);

        transfer::transfer(Donut {
            id: object::new(ctx)
        }, tx_context::sender(ctx))
    }

    /// Consume donut and get nothing...
    public fun eat_donut(d: Donut) {
        let Donut { id } = d;
        object::delete(id);
    }

    /// Take coin from `DonutShop` and transfer it to tx sender.
    /// Requires authorization with `ShopOwnerCap`.
    public fun collect_profits(
        _: &ShopOwnerCap, shop: &mut DonutShop, ctx: &mut TxContext
    ) {
        let amount = balance::value(&shop.balance);
        let profits = coin::take(&mut shop.balance, amount, ctx);

        transfer::public_transfer(profits, tx_context::sender(ctx))
    }
}

Wrapped  包裹

在Move,可以通过将结构类型的字段放入另一个字段来组织数据结构。

  • 数据结构嵌套
  • Move 中的结构体嵌套
  • 需要 store 能力

结构体的组合和使用十分重要。

直接包装

  • 直接将 Sui 对象作为字段
  • 包装对象不能单独存在
  • 只能通过包装对象访问
  • 无法形成循环包装
  • 支持解包
  • 对象 ID 在包装与解包中保持不变
struct Foo has key {
    id: UID,
    bar: Bar,
}

struct Bar has store {
    value: u64,
}

在这两个结构题中,Bar是一个普通结构体,Fo是一个Sui对象(具有 key 能力)。

struct Bar has key, store {
    id: UID,
    value: u64,
}
//添加了key 能力,就成为了Sui对象

如果将 Bar 类型的 Sui 对象放入 Foo 类型的 Sui 对象中,则对象类型 Foo 将包装对象类型 Bar。对象类型 Foo 是包装器或包装对象

在 Sui 中,为了将一个结构体类型嵌入到另一个结构体类型中,被嵌入的类型必须具有 store 能力。而当结构体类型被嵌入到具有 key 能力的 Sui 对象结构体中时,它也成为一个 Sui 对象类型。

通过 Option 包装

  • 灵活性
  • 可选的包装对象
  • 可更换的包装内容
struct SimpleWarrior has key {
    id: UID,
    sword: Option<Sword>,
    shield: Option<Shield>,
}

struct Sword has key, store {
    id: UID,
    strength: u8,
}

struct Shield has key, store {
    id: UID,
    armor: u8,
}

public fun create_warrior(ctx: &mut TxContext) {
    let warrior = SimpleWarrior {
        id: object::new(ctx),
        sword: option::none(),
        shield: option::none(),
    };
    transfer::transfer(warrior, tx_context::sender(ctx))
}
public fun equip_sword(warrior: &mut SimpleWarrior, sword: Sword, ctx: &mut TxContext) {
    if (option::is_some(&warrior.sword)) {
        let old_sword = option::extract(&mut warrior.sword);
        transfer::transfer(old_sword, tx_context::sender(ctx));
    };
    option::fill(&mut warrior.sword, sword);
}

通过 vector 包装

  • 同类型对象的集合包装
  • 类似于 Option 包装
struct Pet has key, store {
    id: UID,
    cuteness: u64,
}

struct Farm has key {
    id: UID,
    pets: vector<Pet>,
}

Sui Move 中有四种能力控制特定类型的值如何使用(赋予的权限)。

类型的值如何被使用,这些能力是:copydropstorekey。

相当于游戏中的职业,法师,射手等,具有不同的技能,职责就不同。

enum MoveAbility {
  COPY //允许复制值。
  DROP //允许弹出/删除值。
  KEY //允许将值直接保存在全局存储中。
  STORE //允许将值保存在全局存储中的结构内。
}

drop

允许在不再需要的某个结构题将其删除,没有drop能力是不允许被忽略的,防止被随意丢弃。这个能力也是为了防止资产泄漏或错误处理。而具有单个 drop 能力的结构称为 Witness

module book::drop_ability;

/// This struct has the `drop` ability.
public struct IgnoreMe has drop {
    a: u8,
    b: u8,
}

/// This struct does not have the `drop` ability.
public struct NoDrop {}

#[test]
// Create an instance of the `IgnoreMe` struct and ignore it.
// Even though we constructed the instance, we don't need to unpack it.
fun test_ignore() {
    let no_drop = NoDrop {};
    let _ = IgnoreMe { a: 1, b: 2 }; // no need to unpack

    // The value must be unpacked for the code to compile.
    let NoDrop {} = no_drop; // OK
}

copy

我们可以使用copy自定义类型来允许实例被复制。

public struct Copyable has copy {}

copy在Move中允许类型的实例或值被复制,但Move的资源模型默认是不允许复制的。

copy能力允许隐式和显式复制。隐式复制发生在赋值操作中,而显式复制可以通过解引用操作符实现。

copy能力通常搭配drop能力一起使用。


let a = Copyable {};
let b = a;   // `a` is copied to `b`
let c = *&b; // explicit copy via dereference operator

let Copyable {} = a; // doesn't have `drop`
let Copyable {} = b; // doesn't have `drop`
let Copyable {} = c; // doesn't have `drop`

在move中,所有的原生类型和标准库中定义的类型都具有 copydrop能力,并且有Move编译器进行内存管理。

key

允许结构体被存储,并且第一个字段为UID类型,确保对象的唯一性和非可丢弃性。可以直接由账户或者地址拥有。

具有key能力,就不能有 dropcopy。又因为UID 的存在,Move的原生类型和标准类型都没有key 能力,这能力仅适用于Sui框架和自定义的类型。

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

/// Creates a new Object with a Unique ID
public fun new(name: String, ctx: &mut TxContext): Object {
    Object {
        id: object::new(ctx), // creates a new UID
        name,
    }
}

Store

store能力在 Move 中能将数据持久化存储在区块链上,它可以允许开发者在Move模块中定义存储和检索的数据结构。

/// This type has the `store` ability.
public struct Storable has store {}

/// Config contains a `Storable` field which must have the `store` ability.
public struct Config has key, store {
    id: UID,
    stores: Storable,
}

/// MegaConfig contains a `Config` field which has the `store` ability.
public struct MegaConfig has key {
    id: UID,
    config: Config, // there it is!
}

store 与 key 的关系

store 能力通常与 key 能力一起使用。key 能力用于访问和修改存储在区块链上的数据。在 Move 中,每个存储的数据项都对应一个唯一的 key

  • key 用于指向存储在区块链上的数据项的位置。
  • store 能力通过 key 来读取和写入数据。

因此,store 能力需要 key 来操作存储的数据,两者是紧密相关的。通过 key,程序可以定位到特定的数据项,并通过 store 能力对其进行读写操作。

💧  HOH水分子公众号

🌊  HOH水分子X账号

⭐️ HOH水分子Github社区

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

0 条评论

请先 登录 后评论
EGAL
EGAL
江湖只有他的大名,没有他的介绍。