Sui Move:基本概览一

news2025/1/15 22:34:56

Module (模块)

  • Move 代码被组织成模块, 可以把一个模块看成是区块链上的一个智能合约

  • 可以通过调用这些模块中的函数来与模块进行交互,可以通过事务或其他 Move 代码来实现, 事务将被发送到并由Sui区块链进行处理,一旦执行完成,结果的更改将被保存

  • 一个模块由 module 关键字 + 地址 + 模块名组成, 其中地址可以写成 alias (定义在 Move.toml中), 例如 lets_move_sui

    module lets_move_sui::sui_fren {
    
    }
    

基本数据类型

  • 无符号整数:  u8u16u32u64u128u256
  • Boolean: bool
  • Addresses: address
  • 字符串: String
  • Vector: vector, 例如 vector<u64>
  • 自定义的结构体类型, 例如下面定义的 Struct

Struct (结构体)

  • 结构体是 Sui Move 中的一个基本概念

  • 结构体可以看成是一组相关字段的组合, 每个字段都有自己的类型

  • Sui Move 可以为结构体添加4 种能力: key、store、drop、copy, 这些能力后续会慢慢涉及

  • 下面是一个基本的结构体名为 AdminCap, 内部含有一个 num_frens字段

        public struct AdminCap {
            num_frens: u64,
        }
    
  • 添加一个私有函数 init, 这是一个特殊的函数, 会在 module 部署到区块链时, 自动调用

        fun init(ctx: &mut TxContext) {
            let admin_cap = AdminCap {
                id: object::new(ctx),
                num_frens: 1000,
            };
            transfer::share_object(admin_cap);
        }
    

Object

  • Object 是 Sui 中的一个基本概念
  • 在 Sui 中, 所有数据可以视为不同 Object 内部的字段
  • 使用结构体(Struct)来表示Object
  • 可以根据 module 中定义的函数进行创建, 读取, 修改,交互 Object

创建一个 Object

  • 一个 Object 一般都有 key 能力以及含有一个类型为 UID 的 id 字段

    • sui::object::new : 创建一个新对象。返回必须存储在 Sui 对象中的 UID

          public fun new(ctx: &mut TxContext): UID {
              UID {
                  id: ID { bytes: tx_context::fresh_object_address(ctx) },
              }
          }
      
  • 创建 Ticket: create_ticket

  • 示例代码

    module lets_move_sui::ticket_module {
        use sui::clock::{Self, Clock};
        use sui::object::{Self, ID, UID};
        use sui::transfer;
        use sui::tx_context::{Self, TxContext};
    
        public struct Ticket has key {
            id: UID,
        }
        
        public fun create_ticket(ctx: &mut TxContext, clock: &Clock) {
            let uid = object::new(ctx);
            let ticket = Ticket {
                id: uid,
                expiration_time: clock::timestamp_ms(clock),
            };
            transfer::transfer(ticket, tx_context::sender(ctx));
        }
    }
    

读取 Ojbect 中的字段

  • 一个 Ticket 一般都有过期时间

    • 在 Ticket 结构体中添加一个 expiration_time 字段
    • 在 ticket_module 中添加一个 is_expired 方法来检测是否过期
module lets_move_sui::ticket_module {
    use sui::clock::{Self, Clock};
    use sui::object::{Self, ID, UID};
    use sui::transfer;
    use sui::tx_context::{Self, TxContext};

    public struct Ticket has key {
        id: UID,
        expiration_time: u64,
    }
    
    public fun create_ticket(ctx: &mut TxContext, clock: &Clock) {
        let uid = object::new(ctx);
        let ticket = Ticket {
            id: uid,
            expiration_time: clock::timestamp_ms(clock),
        };
        transfer::transfer(ticket, tx_context::sender(ctx));
    }
    
    public fun is_expired(ticket: &Ticket, clock: &Clock): bool {
        ticket.expiration_time <= clock::timestamp_ms(clock)
    }
}

修改 Object 中的字段

  • 需要在函数中传入一个可变引用

    module 0x123::my_module {
       use std::vector;
       use sui::object::{Self, UID};
       use sui::transfer;
       use sui::tx_context::TxContext;
    
       struct MyObject has key {
           id: UID,
           value: u64,
       }
    
       fun init(ctx: &mut TxContext) {
           let my_object = MyObject {
               id: object::new(ctx),
               value: 10,
           };
           transfer::share_object(my_object);
       }
    
       public fun set_value(global_data: &mut MyObject, value: u64) {
           global_data.value = value;
       }
    }
    

删除一个 Object

  • sui::object::delete : 删除该对象及其 UID 。这是消除 UID 的唯一方法

        public fun delete(id: UID) {
            let UID { id: ID { bytes } } = id;
            delete_impl(bytes)
        }
    
  • 示例代码

    module 0x123::ticket_module {
      use sui::clock::{Self, Clock};
      use sui::object::{Self, UID};
      use sui::transfer;
      use sui::tx_context::TxContext;
     
      struct Ticket has key {
          id: UID,
          expiration_time: u64,
      }
     
      public fun clip_ticket(ticket: Ticket) {
         let Ticket {
             id,
             expiration_time: _,
         } = ticket;
         object::delete(id);
      }
    }
    

Math

  • 在 Move 中数学运算和其他编程语言非常相似
  • 需要注意的是 x^y 表示 以 x 为底, 指数为 y

类型转换

  • 相同的类型可以直接进行算术运算, 但是不同的类型之间想要进行算术运算, 则需要进行转换

  • 在 Move 中类型转换可以使用这种形式: (x as <type>), 例如(x as u64)

    fun mixed_types_math_error(): u64 {
       let x: u8 = 1;
       let y: u64 = 2;
       // This will fail to compile as x and y are different types. One is u8, the other is u64.
       x + y
    }
    
    fun mixed_types_math_ok(): u64 {
       let x: u8 = 1;
       let y: u64 = 2;
       
       // Ok
       (x as u64) + y
    }
    

Vector

  • vector 相当于是一个动态数组, 这是 Move 内置的一个数据结构, 后续会了解到更多

  • 创建 vector

       // The empty vector does not yet have a type declared. The first value added will determine its type.
       let empty_vector = vector[];
       let int_vector = vector[1, 2, 3];
       let bool_vector = vector[true, true, false];
    
  • vector in struct field

       struct MyObject has key {
           id: UID,
           values: vector<u64>,
           bool_values: vector<bool>,
           address_values: vector<address>,
       }
    

Public function and Private function

  • init 函数必须是 Private 的, 它会在合约部署的时候由 Sui 虚拟机(VM)调用
  • Public 意味着它可以被任何其他的 Move module 和 transactions 调用
  • Private 意味着只能被当前 Move module 调用, 并且不能从 transaction 中调用
module lets_move_sui::sui_fren {
    use sui::tx_context::{Self, TxContext};
    use sui::transfer;
    use sui::object::{Self, ID, UID};
    use std::string::String;
    // use std::vector; // built-in
    use sui::event;

    public struct AdminCap has key {
        id: UID,
        num_frens: u64,
    }

    public struct SuiFren has key {
        id: UID,
        generation: u64,
        birthdate: u64,
        attributes: vector<String>,
    }
    
    fun init(ctx: &mut TxContext) {
        let admin_cap = AdminCap {
            id: object::new(ctx),
            num_frens: 10^3, // 1000
        };
        transfer::share_object(admin_cap);
    }
    
    // change the mint function to transfer the object to the sender
    public fun mint(generation: u64, birthdate: u64, attributes: vector<String>, ctx: &mut TxContext) {
        let uid = object::new(ctx);
        let sui_fren = SuiFren {
            id: uid,
            generation,
            birthdate,
            attributes,
        };
        transfer::transfer(sui_fren, tx_context::sender(ctx));
    }

    public fun burn(sui_fren: SuiFren) {
        let SuiFren {
            id,
            generation: _,
            birthdate: _,
            attributes: _,
        } = sui_fren;
        object::delete(id);
    }
    
    public fun get_attributes(sui_fren: &SuiFren): vector<String> {
        sui_fren.attributes
    }

    public fun update_attributes(sui_fren: &mut SuiFren, attributes: vector<String>) {
        sui_fren.attributes = attributes;
    }
}

Shared Object and Owned Object

  • Shared Objects 可以被任何用户读取和修改

    • 不能并行处理(例如修改), 并且需要严格的检查, 性能慢, 可扩展性差
  • Owned Objects 是私有对象,只有拥有它们的用户才能读取和修改(所有权)

    • 只允许直接所有权,因此如果用户A拥有对象B,而对象B拥有对象C,则用户A无法发送包含对象C的事务, 这个问题可以使用  Receiving<T>  解决(后续会提及)
    • 可以并行处理, 因为涉及它们的 transaction (事务) 不会相互重叠
  • sui::transfer::share_object : 将给定的对象转换为一个可变的共享对象,每个人都可以访问和修改

    public fun share_object<T: key>(obj: T) {
        share_object_impl(obj)
    }
    
  • sui::transfer::transfer : 将 obj 的所有权转移给接收者。obj 必须具有 key 属性

    public fun transfer<T: key>(obj: T, recipient: address) {
        transfer_impl(obj, recipient)
    }
    
  • 示例代码

    module lets_move_sui::shared_and_owned {
        use sui::object::{Self, UID};
        use sui::tx_context::{Self, TxContext};
        use sui::transfer;
        public struct SharedObject has key {
            id: UID,
        }
    
        public struct OwnedObject has key {
            id: UID,
        }
    
        public fun create_shared_object(ctx: &mut TxContext) {
            let shared_object = SharedObject {
            id: object::new(ctx),
            };
            transfer::share_object(shared_object);
        }
    
        public fun create_owned_object(ctx: &mut TxContext) {
            let owned_object = OwnedObject {
                id: object::new(ctx),
            };
            transfer::transfer(owned_object, tx_context::sender(ctx));
        }
    }
    

Event (事件)

  • 什么是 Event? Event 是你的module 将区块链上发生的事情传达给应用程序前端的一种方式

  • 应用程序可以监听某些 Event 来采取行动

  • Event 主要用来给”链下”组件 与 “链上”组件进行交互

  • sui::event::emit : 发出自定义的 Move Event,将数据发送到链下。 由下面的函数签名可知, emit 的参数需要一个包含 copy 和 drop 能力的类型

    public native fun emit<T: copy + drop>(event: T);
    
  • 示例代码

    module 0x123::ticket_module {
      use sui::clock::{Self, Clock};
      use sui::event;
      use sui::object::{Self, ID, UID};
      use sui::transfer;
      use sui::tx_context::{Self, TxContext};
     
      struct Ticket has key {
          id: UID,
          expiration_time: u64,
      }
     
      struct CreateTicketEvent has copy, drop {
         id: ID,
      }
     
      struct ClipTicketEvent has copy, drop {
         id: ID,
      }
     
       public fun create_ticket(ctx: &mut TxContext, clock: &Clock) {
         let uid = object::new(ctx);
         let id = object::uid_to_inner(&uid);
         let ticket = Ticket {
               id: uid,
               expiration_time: clock::timestamp_ms(clock),
         };
         transfer::transfer(ticket, tx_context::sender(ctx));
         event::emit(CreateTicketEvent {
             id,
         });
       }
     
      public fun clip_ticket(ticket: Ticket) {
         let Ticket { id, expiration_time: _ } = ticket;
         object::delete(id);
         event::emit(ClipTicketEvent {
            id: object::uid_to_inner(&id),
         });
      }
    }
    

总结

模块(module) 组织

Move代码被组织成模块,每个模块类似于其他区块链上的单个智能合约。这种模块化设计在Sui中得到了强调,旨在促使开发者保持模块小巧且分布在不同文件中,同时坚持清晰的数据结构和代码规范。这样做既方便应用程序集成,也便于用户理解。

API和交互

模块通过入口和公共函数提供API,用户可以通过事务或其他Move代码调用这些函数来与模块交互。这些交互由Sui区块链处理,并且会保存任何结果变更。

结构体(Struct)

结构是由相关字段组成的集合,每个字段都有自己的类型,如数字、布尔值和向量。每个结构都可以拥有“能力”,包括键(key)、存储(store)、放置(drop)、复制(copy)。这些能力描述了结构在语言中的行为方式。

数据类型 (data type)

Sui Move 支持以下数据类型:无符号整数、布尔值、地址、字符串、向量以及自定义结构类型

对象 (object)

理解对象的生命周期、如何阅读、更新以及删除对象是学习Move语言的重要部分。此外,还需要区分共享对象与拥有对象的概念。

向量 (vector)

向量被理解为动态数组,对于管理智能合约中的项目列表至关重要,反映了区块链应用程序中对于灵活数据结构的需求。

事件 (event)

事件是模块用来通知应用程序前端区块链上发生了某些事情的一种方式。应用可以监听特定的事件,并在这些事件发生时采取行动。

函数 (fun)

  • 公共函数(使用关键字public):可以从任何其他Move模块和事务中被调用。
  • 私有函数(使用关键字private):只能在同一个模块中调用,不能从事务中调用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2277207.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

1/13+2

运算符重载 myString.h #ifndef MYSTRING_H #define MYSTRING_H #include <cstring> #include <iostream> using namespace std; class myString {private:char *str; //记录c风格的字符串int size; //记录字符串的实际长度int capacity; …

GD32F470Z外部晶振不起振

亲测&#xff0c;主要的原因是因为系统配置里面选择的晶振&#xff0c;选择内部还是外部的无源晶振。 1.无源晶振 打开startup_gd32f450_470.s这个起始文件。 ​​​​​​​ ​​​​​​​ 找到SystemInit。 跳进去这个函数。 在这个函数里面最底下找到sys…

用css和html制作太极图

目录 css相关参数介绍 边距 边框 伪元素选择器 太极图案例实现、 代码 效果 css相关参数介绍 边距 <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title><style>*{margin: 0;padding: 0;}div{width: …

【2025 Rust学习 --- 17 文本和格式化 】

字符串与文本 Rust 的主要文本类型 String、str 和 char 内容概括&#xff1a; Unicode 背景知识&#xff1f;单个 Unicode 码点的 char&#xff1f;String 类型和 str 类型都是表示拥有和借用的 Unicode 字符序列。Rust 的字符串格式化工具&#xff0c;比如 println! 宏和 …

C#中颜色的秘密

颜色的秘密: 颜色Color是一个调色板, 所有颜色都是由透明度Alpha,红Red,绿Green,蓝Blue按不同比例调色混合而成,如果不考虑透明度Alpha,颜色共有256*256*25616777216种 ColorARGB A,R,G,B都为byte型[8位],因此可以用整体的32个整数[Int32]来表示一种颜色 Color 所属命名空…

Pycharm 使用教程

一、基本配置 1. 切换Python解释器 pycharm切换解释器版本 2. pycharm虚拟环境配置 虚拟环境的目的&#xff1a;创建适用于该项目的环境&#xff0c;与系统环境隔离&#xff0c;防止污染系统环境&#xff08;包括需要的库&#xff09;虚拟环境配置存放在项目根目录下的 ven…

phpenc加密程序源码

免费扩展加密程序&#xff0c;类似于sg11加密&#xff0c;支持单个PHP&#xff08;免费&#xff09;文件以及批量PHP文件&#xff08;ZIP压缩包格式&#xff09;源码加密的保护平台&#xff0c;加密后的源码文件保持原有代码结构&#xff0c;可以跨平台运行&#xff0c;可以运行…

视频转码对画质有影响吗?视频融合平台EasyCVR支持哪些转码格式?

视频转码过程是将视频文件从一种编码格式转换为另一种格式的过程&#xff0c;这一过程在现代数字媒体中扮演着至关重要的角色。众所周知&#xff0c;视频转码不仅仅是简单的格式转换&#xff0c;它涉及多个关键参数的改变&#xff0c;例如视频编码格式、比特率、分辨率以及帧率…

LeetCode热题100(哈希篇)

题目出自Leetcode热题100&#xff1a;Leetcode热题100 文章目录 1. 两数之和思路代码CJavaPython 49. 字母异位词分组思路代码CJavaPython 128. 最长连续序列思路代码CJavaPython 总结 1. 两数之和 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找…

python学opencv|读取图像(三十一)缩放图像的三种方法

【1】引言 前序学习进程中&#xff0c;我们至少掌握了两种方法&#xff0c;可以实现对图像实现缩放。 第一种方法是调用cv2.resize()函数实现&#xff0c;相关学习链接为&#xff1a; python学opencv|读取图像&#xff08;三&#xff09;放大和缩小图像_python opencv 读取图…

rk3568 , buildroot , qt ,使用sqlite, 动态库, 静态库

问题说明&#xff1a; 客户反馈 &#xff0c;buildroot 系统 &#xff0c;使用qt 使用sqlite &#xff0c;有报错&#xff0c;无法使用sqlite. 测试情况说明&#xff1a; 我自己测试&#xff0c;发现&#xff0c; buildroot 自己默认就是 使能了 sqlite 的。 是否解决说明&…

Windows图形界面(GUI)-QT-C/C++ - Qt图形绘制详解

公开视频 -> 链接点击跳转公开课程博客首页 -> ​​​链接点击跳转博客主页 目录 Qt绘图基础 QPainter概述 基本工作流程 绘图事件系统 paintEvent事件 重绘机制 文字绘制技术 基本文字绘制 ​编辑 高级文字效果 基本图形绘制 线条绘制 ​编辑 形状绘制 …

OpenArk64:Windows 系统分析与逆向工程工具详解

引言 在 Windows 系统的底层操作和逆向工程领域&#xff0c;OpenArk 是一款备受推崇的开源工具集。而 OpenArk64.exe 是 OpenArk 工具的 64 位版本&#xff0c;专门用于 64 位 Windows 系统。它提供了强大的功能&#xff0c;帮助用户深入分析系统内核、进程、文件、注册表等&a…

浅谈计算机网络02 | SDN控制平面

计算机网络控制平面 一、现代计算机网络控制平面概述1.1 与数据平面、管理平面的关系1.2 控制平面的发展历程 二、控制平面的关键技术剖析2.1 网络层协议2.1.1 OSPF协议2.1.2 BGP协议 2.2 SDN控制平面技术2.2.1 SDN架构与原理2.2.2 OpenFlow协议2.2.3 SDN控制器 一、现代计算机…

【C++】PP5015 [NOIP2018 普及组] 标题统计

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;题目背景题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 样例 #2样例输入 #2样例输出 #2 提示数据规模与约定 &#x1f4af;方法分析方法1&#xff1a;我的做法实…

从玩具到工业控制--51单片机的跨界传奇【2】

咱们在上一篇博客里面讲解了什么是单片机《单片机入门》&#xff0c;让大家对单片机有了初步的了解。我们今天继续讲解一些有关单片机的知识&#xff0c;顺便也讲解一下我们单片机用到的C语言知识。如果你对C语言还不太了解的话&#xff0c;可以看看博主的C语言专栏哟&#xff…

线程池面试题目集合

最近面试中总是问到ThreadPoolExecutor类相关问题&#xff0c;在此集中整理下。 问题1.ThreadPoolExecutor的关键参数是哪些&#xff0c;任务添加过程中&#xff0c;内部线程是怎样构建的&#xff1f; a)任务到达时&#xff0c;线程池数目小于核心线程数corePoolSize&#xff0…

程序员独立开发竞品分析:确定网站使用什么建站系统

要确定一个网站使用的建站系统&#xff0c;可以通过以下几种方法尝试分析&#xff1a; 查看页面源代码&#xff1a; 打开网站&#xff0c;右键点击页面并选择“查看页面源代码”。在代码中查找一些常见的建站系统标志&#xff0c;例如&#xff1a; WordPress 的迹象&#xff1a…

基于Media+Unity的手部位姿三维位姿估计

使用mediapipe Unity 手部位姿三维位姿估计 参考文章 基于Mediapipe的姿势识别并同步到Unity人体模型中 MediapipeUnity3d实现虚拟手_unity mediapipe-CSDN博客 需求 我的需求就是快速、准确的跟踪手部位姿并实现一个三维显示。 主要思路 搭建mdeiapipe系统&#xff0c…

构建高性能网络服务:从 Socket 原理到 Netty 应用实践

1. 引言 在 Java 网络编程中&#xff0c;Socket 是实现网络通信的基础&#xff08;可以查看我的上一篇博客&#xff09;。它封装了 TCP/IP 协议栈&#xff0c;提供了底层通信的核心能力。而 Netty 是在 Socket 和 NIO 的基础上&#xff0c;进一步封装的高性能、异步事件驱动的…