Move 支持高阶函数值

  • aptoslabs
  • 发布于 2025-12-02 12:18
  • 阅读 12

本文介绍 Aptos Move 1.35/Move 2.2 引入的高阶函数值:函数可像普通值一样被构造、传递和存储,从而支持更灵活的应用组合。文章通过游戏协作、权限化存储、回调式访问与重入安全等示例,说明这一能力如何提升模块解耦、动态调用和框架设计。最后还提到函数值的形式化验证正在推进中,整体展示了 Move 在可组合性与安全性上的新进展。

Move 支持 Higher Order

随着 Aptos 1.35 的发布,Move VM 已在主网上支持作为一等公民的 higher order function values。也就是说,函数像整数、struct 和其他值一样,也成为了值。这些值可以通过 lambda 构造,作为参数在执行栈中传递,并存储在持久化资源中。

Function values 为开发者带来了重大的新能力,可以说这是自 Meta 创建 Move 1.0 以来最重要的能力之一(而且仅在 Aptos Move 中可用)。

除了开发者已经在 TypeScript 等客户端语言中熟悉和喜爱的函数式编程模式之外,它们还使 Aptos 上安全连接的应用能够以可扩展、模块化的方式进行组合。

那么,这股热潮究竟源自什么?本文将通过一些示例来说明。

背景

该特性最早于一月份通过 AIP 112 引入。请查看参考文档

连接的应用

如今,如果两个应用想要交互并在一笔交易中完成结算,它们必须通过直接的编译时依赖来实现。借助 function values,这一点可以避免。考虑一个协调多个玩家的游戏应用。系统会依次要求每个玩家出价,而他们随后可能会获胜。在 Move 2.2 中,我们可以如下表示:

module game::game {
    struct Player has store {
        /// 一个返回玩家出价的函数。
        bid: ||u128 has store,
        /// 一个接收给定获胜金额的函数。
        win: |u128| has store
    }

    struct Game has key {
        players: vector<Player>,  // 已注册玩家
        pot: u128,                // 累积的出价
        next: u64,                // 下一位玩家的回合
    }

    /// 玩家加入(其他 app 连接)。
    public fun join(s: &signer, bid: ||u128 has store, win: |u128| has store) {
        Game[s].players.push_back(Player{bid, win})
    }
}

将一个玩家连接到游戏 app,本质上就是该玩家执行一笔交易,并通过公共的 join 函数注册自己:

module player::player {
    use game::game;

    entry fun init(s: &signer) {
 let a = s.address_of();
 game::join(|| bid(a), |x| win(a, x))
    }

    #[persistent] fun bid(a: address): u128 { .. }
    #[persistent] fun win(a: address, amount: u128) { .. }
}

注意,通过 #[persistent] 属性,标记的函数必须遵循 Move 的 public function 升级兼容性规则:这些函数不能被移除,签名也不能被修改。

这保证了在未来任何交易中,面向玩家的动态 API 都是明确定义的,并且这是所有具有 store ability 的 function value 的要求。

为了补全这个示例,下面给出游戏逻辑的一个可能草图。

module game::game {
    entry fun step(s: &signer): bool {
        let Game{ players, pot, next } = &mut Game[s];
        let player_count = players.length();
        let Player{bid, win} = &game.players[*next];
        *pot += bid();
        if (aptos_framework::randomness::u64_range(0, player_count) == next) {
            win(*pot);
            *pot = 0
        }
        *next = (*next + 1) % playercount;
    }
}

在这个示例中,我们按轮询顺序遍历已注册玩家列表,并随机让其中一位玩家赢得累积的 ‘pot’。

记住我以便更快登录

在 step 交易执行期间,只会执行已注册玩家中的 一位 的代码。Move 2.2 保证,存储的 function value 所对应的代码,只有在函数真正执行时才会被加载。这使得游戏能够处理许多不同的玩家实现,并且只加载交易期间实际需要的那些实现。

分层框架

在 Move 2.2 之前,很难构建能够将全局数据的访问控制与功能逻辑分离的框架。这一情况随着 Move 2.2 中的 continuation-based 编程而改变。

考虑一个用于受权限控制的全局数据存储的框架模块。假设 signer 关联了一组权限,那么可以定义如下 API,它会完全控制哪些账户可以访问已存储的数据:

module framework::permissioned_store {
    struct S<A:store> has key { value: A }

    public fun publish<A: store>(item: &signer, value: A) {
        move_to<S<A>>(item, S{value})
    }

    /// 只有允许读取的 signer 才能访问 &A
    public fun access<A: store>(acc: &signer, item: address, action: |&A|B): B {
        check_read_perm(acc);
        action(&S<A>[item].value)
    }

    /// 只有允许写入的 signer 才能访问 &mut A
    public fun access_mut<A: store>(acc: &signer, item: address, action: |&mut A|B): B {
        check_write_perm(acc);
        action(&mut S<A>[item].value)
    }
}

在 Move 2.2 之前,从技术上讲,不可能像上面的 action continuations 那样将处理逻辑与权限检查分离,因为函数无法返回对资源的引用。在 Move 2.2 中,这些引用可以像示例中那样传递给 continuations。

Reentrancy 安全

在 Move 2.2 之前,模块代码不可能发生 reentrancy。当一个模块调用另一个模块中的函数时,后者无法回调到调用方模块。这是因为 Move 中模块之间的使用关系是无环的。

然而,function values 使 reentrancy 成为可能。事实上,这是一种非常常见的编程模式。例如,perm_store::access(acc, item, my_accessor) 就体现了 reentrancy:我们调用另一个模块中的函数,而它会通过 my_accessor 回调回来。

在 Move 2.2 中,reentrancy 是被允许的,但当模块被重新进入时,对该模块中任何资源的访问都会被锁定。这使得如下这种自然的 reentrancy 保护成为可能:

let state = &mut S[s]; // 保留对全局状态的访问
callback();            // 调用其他代码,任何尝试修改 `S` 的操作都会中止
work(state);

除了这个内置的 reentrancy 检查之外,还提供了一个可选的模块级 reentrancy lock。

更多细节请参见 Move book 中关于 reentrancy 的部分。

形式化验证

function values 的形式化验证仍在开发中,但我们已经对其支持范围形成了一些预期。

可以对函数参数的行为进行规定,例如下面这样,我们要求传入的函数绝不会中止:

fun run(f: |u64|, x: u64) {
  f(x)
}
spec run {
  spec f {
    aborts_if false;
  }
  aborts_if false;
}

上面的函数规范可以被验证,因为我们可以假设 f 不会中止。在调用 run(some_f, x) 的代码位置,必须验证 some_f 的确不会中止。

使用 Function Values

Function values 已经可以直接使用。安装最新的 Aptos CLI并开始体验吧!

  • 原文链接: medium.com/aptoslabs/mov...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

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