当前位置: 首页 > news >正文

IOTA 学习笔记(五):对象模型是理解 IOTA 的关键

前几期我们先从 IOTA 的历史讲起,理解了 Tangle、DAG、Coordinator、Coordicide、Stardust 和 Rebased。上一期开始进入当前 IOTA 架构,提到了网络层、共识层、执行层、状态层和开发工具链。

从这一期开始,我们要真正接触当前 IOTA 开发中最重要的概念之一:对象模型。

如果说 Tangle 是理解早期 IOTA 的关键,那么对象模型就是理解当前 IOTA 的关键。因为 Rebased 之后,IOTA 不再只是围绕早期 DAG 账本思想展开,而是进一步采用 MoveVM 和对象模型来支撑智能合约、链上资产和复杂状态管理。

简单来说,在当前 IOTA 中,很多链上状态都可以被理解为对象。代币是对象,合约包是对象,开发者自定义的数据结构也可以成为对象。理解对象,就等于理解当前 IOTA 中“链上状态到底是怎么存在的”。

1. 为什么要理解对象模型

很多人刚开始学习区块链时,会先形成一种账户模型的直觉。

比如在以太坊中,我们经常说某个账户有多少余额,某个合约地址有一片存储空间,合约内部有一些变量。用户调用合约,本质上是修改合约账户下的状态。

这种理解方式可以简单表示为:

账户地址 → 账户余额 合约地址 → 合约存储

但是,在 IOTA 当前架构中,更重要的理解方式是对象模型。

对象模型的直觉是:链上状态不是只挂在某个账户下面的一组变量,而是由一个个独立对象组成。每个对象都有自己的唯一标识、类型、所有者和数据内容。

可以简单表示为:

地址 A → 拥有 Object 1 地址 A → 拥有 Object 2 地址 B → 拥有 Object 3 链上系统 → 存在 Shared Object

这种方式更接近现实世界中“物品”的概念。

比如:

一枚代币是一个对象 一个 NFT 是一个对象 一个合约包是一个对象 一个用户创建的计数器是一个对象 一个共享状态也可以是一个对象

所以,学习 IOTA 不能只问“某个账户里有什么变量”,而要进一步问:

当前交易操作了哪些对象?这些对象属于谁?对象是否可以被修改?对象是否可以被转移?对象是否是共享对象?

这就是对象模型的重要性。

2. 什么是 Object

Object 可以翻译为“对象”。

在 IOTA 中,对象是链上状态的基本单位。一个对象通常包含几个核心信息:

Object ID:对象的唯一标识 Object Type:对象的类型 Owner:对象的所有者 Version:对象版本 Data:对象内部保存的数据 Previous Transaction:产生或修改该对象的上一笔交易

可以把对象想象成链上的一个独立状态单元。它不是临时变量,而是可以被链上系统追踪、查询和操作的状态实体。

例如,一个 Counter 对象可以表示一个计数器:

Object ID: 0xabc... Type: Counter Owner: 0x123... Value: 10 Version: 3

这表示链上有一个 Counter 类型的对象,它属于某个地址,当前计数值是 10,版本号是 3。

如果用户调用 increment 函数,把 value 从 10 改成 11,那么这个对象不会只是“原地无痕变化”,而是会产生新的对象版本。也就是说,IOTA 可以追踪对象随着交易不断变化的历史。

因此,对象不仅表示链上状态,也承担了状态追踪和权限控制的功能。

3. Object ID:对象的唯一身份

每个对象都有一个 Object ID。

Object ID 可以理解为对象在链上的唯一身份。只要知道对象 ID,开发者就可以通过 CLI、SDK 或浏览器查询这个对象的状态。

这和现实世界中的编号很像。比如一张身份证有身份证号,一辆车有车架号,一个快递有运单号。Object ID 就是链上对象的唯一编号。

在后面使用 IOTA CLI 时,经常会看到这样的对象 ID:

0x8a7f... 0x25c3... 0xb91d...

这些 ID 很长,但不用害怕。它们的作用就是告诉系统:我要查询或操作的是哪一个具体对象。

例如,当我们调用某个 Move 函数时,如果这个函数需要修改一个 Counter 对象,那么命令中通常就需要传入这个 Counter 对象的 Object ID。

可以简单理解为:

函数知道怎么修改 Counter Object ID 告诉函数要修改哪一个 Counter

所以,Object ID 是开发者和链上对象交互时最常用的标识之一。

4. Version:为什么对象有版本

对象不仅有 ID,还有版本。

版本的作用是记录对象状态变化。每当对象被交易修改后,都会产生新的版本。

例如,一个 Counter 对象最开始 value = 0,可以看作版本 1:

Counter Object Version: 1 Value: 0

执行一次 increment 后,value 变成 1,对象版本也更新:

Counter Object Version: 2 Value: 1

再执行一次 increment:

Counter Object Version: 3 Value: 2

这样做的好处是,系统可以清楚知道对象状态经历了哪些变化,也可以避免并发交易同时修改同一个对象时造成混乱。

版本号在交易验证中也很重要。因为交易操作对象时,通常不是只说“我要操作这个对象 ID”,还需要对应具体版本。这样可以防止某笔交易基于旧状态执行,导致状态冲突。

可以这样理解:

Object ID 决定“是哪一个对象”,Version 决定“是哪一个状态版本”。

这对区块链系统尤其重要,因为链上状态必须可验证、可追踪、不可随意篡改。

5. Owner:对象属于谁

对象模型中另一个非常重要的概念是 Owner,也就是对象所有者。

在 IOTA 中,对象不是孤立存在的,它通常会有一个所有权模型。所有权决定这个对象能被谁访问、谁能修改、谁能转移,以及是否需要经过共识排序。

常见的所有权类型可以先理解为以下几类:

Owned Object:归某个地址所有 Shared Object:共享对象,可以被多个用户访问 Immutable Object:不可变对象 Wrapped Object:被包裹在另一个对象内部的对象

这几类对象在交易中的行为是不一样的。

Owned Object 比较容易理解。它属于某个地址,通常只有所有者可以把它作为可变对象传入交易中。

Shared Object 则更复杂。它不是只属于某一个用户,而是可以被多个用户访问或修改。因为多个用户可能同时操作它,所以涉及共享对象的交易通常需要经过共识排序。

Immutable Object 是不可变对象。它一旦创建后,状态不会再被修改。智能合约 package 通常就可以理解为不可变对象,因为合约发布后,代码本身不能随意被修改。

Wrapped Object 则表示一个对象被放进另一个对象内部。这个概念后面学习更复杂的 Move 设计时会遇到,入门阶段先知道它存在即可。

6. Owned Object:最容易理解的对象

Owned Object 是最容易理解的一类对象。

它属于某个具体地址。这个地址的拥有者可以在交易中操作这个对象,比如转移、修改或作为参数传给 Move 函数。

例如,用户 A 拥有一个 Counter 对象:

Address A owns Counter Object Counter.value = 0

用户 A 调用 increment 函数后:

Address A owns Counter Object Counter.value = 1

这个过程比较直接,因为对象归用户 A 所有,用户 A 发起交易修改自己的对象。

Owned Object 的特点是:

有明确所有者 通常只能由所有者操作 适合表示个人资产或个人状态 并发冲突相对容易处理

例如,普通代币对象、用户自己的 NFT、个人创建的计数器,都可以看作 Owned Object 的典型例子。

学习 IOTA Move 合约时,刚开始最好先从 Owned Object 入手。因为它的所有权关系最直观,也最容易通过 CLI 查询和调用。

7. Shared Object:为什么共享对象更复杂

Shared Object 是共享对象。

它不只属于某一个地址,而是可以被多个用户访问。共享对象适合表示多人共同交互的链上状态。

比如:

一个公共交易池 一个共享计数器 一个链上投票系统 一个市场合约 一个多人游戏状态

这些状态不是某一个用户自己的私有对象,而是多个用户都可能参与操作。

共享对象的问题在于:如果多个用户同时修改同一个对象,系统必须决定这些操作的执行顺序。

例如,有一个共享计数器 SharedCounter,当前值是 0:

SharedCounter.value = 0

用户 A 和用户 B 同时调用 increment:

用户 A: increment 用户 B: increment

如果两个交易都有效,最终值应该是 2。但是系统必须明确谁先执行、谁后执行。否则不同节点可能得到不同状态。

因此,涉及共享对象的交易通常需要通过共识来排序。

这就是 Shared Object 和 Owned Object 的重要区别:

Owned Object:对象归某个地址所有,操作路径相对简单 Shared Object:多个用户都可能访问,需要共识确定顺序

所以,后面如果你看到某些交易比普通对象交易更复杂,很可能就是因为它涉及共享对象。

8. Immutable Object:不可变对象

Immutable Object 是不可变对象。

顾名思义,它一旦形成,就不能再被修改。不可变对象适合表示不应该被随意更改的链上内容。

最典型的例子就是 Package。

在 IOTA 中,Move 合约发布之后,会形成链上的 Package 对象。这个 Package 保存了合约模块和函数。一般来说,发布后的 Package 是不可变的。开发者可以调用其中的函数,但不能随意修改已经发布的代码内容。

这很好理解。智能合约之所以可信,一个重要原因就是代码发布后不能被随便改。如果合约发布者可以随时修改代码,那么用户就很难信任这个合约。

因此,Package 作为不可变对象,能够保证链上代码的稳定性和可验证性。

可以简单理解为:

Package Object = 发布到链上的 Move 合约代码 Immutable = 发布后不能随意修改

当然,实际开发中可能存在 package upgrade 机制,用于在一定规则下升级合约。但从入门角度看,先把 Package 理解成不可变合约对象,是比较合适的。

9. Package:合约也是对象

在 IOTA 中,合约发布后会形成 Package 对象。

这一点很重要。很多人会把合约理解成某个“程序文件”,但在 IOTA 链上,发布后的合约本身也被表示为对象。

一个 Package 中可以包含多个 Move module。每个 module 中又可以定义 struct 和 function。

可以简单表示为:

Package ├── module A │ ├── struct │ └── function └── module B ├── struct └── function

当开发者发布一个 Move package 后,链上会生成一个 Package ID。之后调用这个合约中的函数时,就需要用到这个 Package ID。

例如,我们发布了一个 Counter 合约,得到:

Package ID: 0xabc...

然后调用其中的函数时,可能需要指定:

0xabc::counter::create 0xabc::counter::increment

这里的0xabc就是 Package ID,counter是模块名,createincrement是函数名。

所以,Package ID 对开发者来说非常重要。它相当于链上合约的地址。

可以这样理解:

Object ID 用来定位对象 Package ID 用来定位合约包 函数路径用来定位具体调用逻辑

10. Coin:代币也是对象

在对象模型下,代币也可以被理解为对象。

很多传统账户模型中,余额像是账户里的一个数字。例如:

Address A balance = 100

但在对象模型中,余额可以由多个 Coin 对象组成。一个地址可能拥有多个 Coin 对象,每个 Coin 对象代表一笔具体的代币金额。

例如:

Address A owns Coin Object 1: 30 Address A owns Coin Object 2: 50 Address A owns Coin Object 3: 20

这三个 Coin 对象加起来,用户 A 的总余额就是 100。

这种设计一开始可能不如账户余额直观,但它有很强的表达能力。因为每个 Coin 都是独立对象,可以被拆分、合并、转移或作为 gas 使用。

比如,一个 Coin 对象可以被拆成两个:

Coin 100 → Coin 40 + Coin 60

两个 Coin 对象也可以合并:

Coin 40 + Coin 60 → Coin 100

这也是为什么在 IOTA CLI 操作中,经常会看到 gas object、coin object、object ID 等概念。因为你的余额不是一个抽象数字,而是由具体对象组成的。

11. 对象和交易的关系

对象模型只有和交易放在一起,才真正容易理解。

一笔交易通常会读取或操作一些对象。交易执行后,这些对象的状态可能发生变化,也可能产生新的对象。

可以把交易看成对象状态转换器:

交易前: Object A Object B Gas Object 交易执行: Move 函数调用 权限检查 Gas 计算 对象读写 交易后: Object A' Object B' New Object C Updated Gas Object

也就是说,交易不是简单地“写一条记录”,而是根据合约逻辑改变链上对象状态。

例如,调用 Counter 的 increment 函数:

输入:Counter Object 执行:value = value + 1 输出:Counter Object 的新版本

再比如,调用 create 函数:

输入:TxContext 执行:创建 Counter Object 输出:新的 Counter Object

因此,学习 IOTA 交易时,最重要的是看清楚:

这笔交易输入了哪些对象? 这些对象是 owned 还是 shared? 函数是否需要 mutable reference? 交易执行后产生了哪些对象? 哪些对象被修改了? 哪些对象被转移了? Gas object 发生了什么变化?

这些问题比单纯记命令更重要。

12. 对象模型和 Move 的关系

IOTA 引入 MoveVM 后,对象模型和 Move 语言紧密结合。

在 Move 中,开发者可以定义 struct。某些 struct 可以成为链上对象。通常,一个可以成为链上对象的 struct 会包含 UID。

可以用简化方式理解:

public struct Counter has key { id: UID, value: u64, }

这里的 Counter 是一个结构体。它有key能力,说明它可以作为链上对象存在。id: UID则表示它具有链上对象身份。

后面编写合约时,我们会经常看到类似结构。

例如:

public fun create(ctx: &mut TxContext) { let counter = Counter { id: object::new(ctx), value: 0, }; transfer::transfer(counter, tx_context::sender(ctx)); }

这段逻辑可以简单理解为:

创建一个新的 Counter 对象 给它分配唯一 ID 把它转移给交易发送者

这就是对象模型和 Move 合约结合的典型方式。

因此,学习 Move 时不要只看语法,而要一直追问:这个 struct 会不会成为对象?这个函数创建了什么对象?对象转移给了谁?对象是否可变?对象能不能被共享?

13. 对象模型和账户模型的区别

现在可以系统对比一下对象模型和账户模型。

账户模型更像这样:

账户 A: balance = 100 storage = {...} 合约 C: variable1 = ... variable2 = ...

对象模型更像这样:

Address A owns: Coin Object 1 Coin Object 2 NFT Object Counter Object Shared: Market Object Registry Object Immutable: Package Object

账户模型强调“账户下面有什么状态”。
对象模型强调“链上有哪些对象,这些对象属于谁”。

这会影响开发者的思维方式。

在账户模型中,你可能会问:

这个账户余额是多少? 这个合约变量是多少?

在对象模型中,你更应该问:

这个地址拥有哪些对象? 这个对象的 ID 是什么? 这个对象的 owner 是谁? 这个对象能不能被修改? 这个对象是否是 shared? 这个对象由哪笔交易创建或修改?

这就是 IOTA 当前开发方式和很多传统智能合约平台的不同之处。

14. 初学者最容易混淆的几个点

学习对象模型时,初学者容易混淆几个问题。

第一个问题:Object ID 和 Package ID 是不是一回事?

它们本质上都是链上对象的 ID,但用途不同。普通 Object ID 用来定位具体链上对象,例如 Counter、Coin、NFT。Package ID 用来定位发布后的合约包。

第二个问题:地址是不是对象?

地址本身不是普通对象。地址是账户身份或所有者标识,对象可以归属于地址。可以说地址拥有对象,但不要把地址本身简单等同于对象。

第三个问题:Coin 为什么也是对象?

因为在对象模型下,代币余额可以由多个 Coin 对象组成。每个 Coin 对象都有自己的 ID 和金额,可以被拆分、合并或转移。

第四个问题:Shared Object 是不是所有人都能随便改?

不是。Shared Object 可以被多个用户访问,但具体谁能改、怎么改,仍然取决于 Move 合约函数中的权限逻辑。共享不等于无权限控制。

第五个问题:Package 发布后还能不能改?

入门阶段可以先理解为 Package 是不可变对象。实际开发中可能涉及升级机制,但升级也需要遵守特定规则,不是随意修改链上代码。

15. 小结

这一期主要讲了 IOTA 的对象模型。

在当前 IOTA 中,对象是链上状态的基本单位。每个对象都有自己的 Object ID、类型、所有者、版本和数据。对象可以归某个地址所有,也可以是共享对象、不可变对象,或者被包裹在其他对象内部。

对象模型改变了我们理解链上状态的方式。传统账户模型更关注“账户下面有什么状态”,而对象模型更关注“链上有哪些对象、对象属于谁、对象如何被交易操作”。

这也是为什么后面学习 IOTA Move 合约时,必须先理解对象模型。因为 Move 合约并不是孤立执行的代码,它总是在创建、读取、修改、转移或共享对象。

可以用一句话总结本期内容:

当前 IOTA 的链上世界,不是由账户变量简单堆起来的,而是由一个个具有身份、所有权和版本的对象组成的。

下一期,我会继续讲 Move 语言入门。重点回答:Move 是什么?module、struct、function 分别是什么?为什么 Move 很适合和对象模型结合?

http://www.rkmt.cn/news/1440081.html

相关文章:

  • 2026真空热压炉、碳化炉、熔炼炉五大厂家推荐 - 资讯速览
  • TranslucentTB启动失败?5步修复Microsoft.UI.Xaml框架缺失问题
  • 2026年 果蔬深加工前处理设备/饮料杀菌及实罐杀菌设备/脱水蔬菜前处理设备实力制造商:智能高效与锁鲜工艺解析 - 品牌企业推荐师(官方)
  • 2026年 果蔬深加工设备/饮料杀菌实罐杀菌设备/脱水蔬菜前处理设备十大品牌推荐:高效节能与卫生安全的行业标杆之选 - 品牌企业推荐师(官方)
  • 终极指南:AlwaysOnTop - 3分钟解决Windows多窗口遮挡难题
  • ThinkPHP后端如何优雅地给uni-app用户发推送?一个云函数搞定全流程
  • 2026执行律师实力推荐:疑难执行领域权威测评,专业执行律师团队推荐 - 资讯快报
  • 手把手教你学Simulink——无刷直流电机(BLDC)霍尔传感器(Hall Sensor)信号处理电路仿真
  • IOTA 学习笔记(六):Move 语言入门
  • 武汉闲置黄金上门回收攻略|余生黄金回收靠谱变现技巧 - 余生黄金回收
  • 告别密码烦恼!在RuoYi-Vue中快速对接公司统一认证平台(JWT单点登录集成指南)
  • 网站新招:利用 FROST 技术分析 SSD 活动,窥探访客信息
  • 树莓派4B新手避坑:从SD卡格式化到VNC远程桌面,保姆级图文教程(含静态IP设置)
  • 2026印刷PVC盒厂家市场观察:交付链路成熟度与选型评估指南 - 企师傅推荐官
  • 绵阳各区卖金去哪不被坑?2026年5月金价985元/克,六家回收店铺上门服务全攻略 - 余生黄金回收
  • 基于YOLO26深度学习的水果识别检测系统(项目源码+数据集+模型权重+UI界面+python+深度学习+远程环境部署)
  • Streamlit(二十)- API 参考文档(十三)- 缓存与状态管理组件
  • Unity官方API真香警告:一行代码隐藏启动Logo,全平台兼容(含WebGL特殊处理)
  • 手把手教你用THB6128驱动模块搞定两相四线步进电机(附PWM控制与细分设置避坑指南)
  • 如何快速部署智慧树学习助手:3步实现高效自动化学习方案
  • UE4本地多人游戏避坑指南:分屏模式下视口渲染异常、UI错位问题排查与修复
  • 2026年西北钢结构工程材料采购:宁夏源头工厂直供 vs 跨省物流踩坑全对比 - 优质企业观察收录
  • 保姆级教程:用tippecanoe和Mapbox GL JS把OSM数据变成可交互的矢量地图(附完整代码)
  • SCREME框架:内存可靠性技术的创新与优化
  • 别再手动K帧了!UE4 Sequence粒子系统批量控制与时间轴优化全攻略
  • S2.1触发设计:如何成为用户的默认选择
  • Vue项目里那个‘滚动到哪从哪开始’的炫酷效果,我是用@david-j/vue-j-scroll插件实现的
  • Arm Compiler 6中RTTI机制解析与嵌入式优化实践
  • 不止于启动:用RealSense和ROS Noetic玩转3D点云可视化与Rviz调试
  • S2.2行动设计:让行为小到不可能失败