Move语言 Signer

在开始使用 Resource 之前,我们需要了解 signer 类型以及这种类型存在的原因。

Signer 是一种原生的类似 Resource 的不可复制的类型,它包含了交易发送者的地址。

Signer 类型代表了发送者权限。换句话说,使用 signer 意味着可以访问发送者的地址和 Resource。它与signature没有直接关系,就 Move VM 而言,它仅表示发送者。

Signer 只有一种 ability: Drop。

脚本的 Signer

Signer 是原生类型,使用前必须先创建。与 vector 这样的原生类型不同,signer 不能直接在代码中创建,但是可以作为脚本参数传递:

script {
    // signer is an owned value
    fun main(account: signer) {
        let _ = account;
    }
}

Signer 参数无需手动将其传递到脚本中,客户端(CLI)会自动将它放入你的脚本中。而且,signer 自始至终都只是引用,虽然标准库中可以访问签名者的实际值,但使用此值的函数是私有的,无法在其他任何地方使用或传递 signer 值。

当前,约定俗成的 signer 类型的变量名是 account

标准库中的 Signer 模块

原生类型离不开原生方法, signer 的原生方法包含在0x1::Signer模块中。这个模块相对比较简单,具体可以参考 Diem 标准库 Signer 模块的实现:

module Signer {
    // Borrows the address of the signer
    // Conceptually, you can think of the `signer`
    // as being a resource struct wrapper arround an address
    // ```
    // resource struct Signer { addr: address }
    // ```
    // `borrow_address` borrows this inner field
    native public fun borrow_address(s: &signer): &address;

    // Copies the address of the signer
    public fun address_of(s: &signer): address {
        *borrow_address(s)
    }
}

模块中包含两个方法,一个是原生方法,另一个是 Move 方法。后者使用更方便,因为它使用了取值运算符来复制地址。

使用起来也非常简单:

script {
    fun main(account: signer) {
        let _ : address = 0x1::Signer::address_of(&account);
    }
}

模块中的 Signer

module M {
    use 0x1::Signer;

    // let's proxy Signer::address_of
    public fun get_address(account: signer): address {
        Signer::address_of(&account)
    }
}

使用&signer作为函数的参数说明该函数正在使用发送者的地址。

引入signer类型的原因之一是要明确显示哪些函数需要发送者权限,哪些不需要。因此,函数不能欺骗用户未经授权访问其 Resource。

Move 白皮书中详细描述了 Resource 这个概念。最初,它是作为一种名为 resource 的结构体类型被实现,自从引入 ability 以后,它被实现成拥有 Key 和&nb ...