A próxima geração de linguagem de desenvolvimento de contrato inteligente Move (7)

prefácio

No artigo anterior, introduzimos principalmente os genéricos na linguagem Move, e aprendemos sobre a definição e uso de genéricos.No Move, os genéricos podem ser usados ​​para estruturas e funções. A estrutura de tipos de dados pode nos ajudar a criar nossos próprios tipos e armazenar estruturas de dados complexas, mas às vezes precisamos de estruturas de dados mais flexíveis, escaláveis ​​e gerenciáveis.Para atender a essa demanda, o Move fornece o Vector.

o que é vetor

Vector é um tipo de dados integrado do Move para armazenar grandes quantidades de dados. Esta é uma solução para coleções de qualquer tipo de dados. Seus recursos são fornecidos pela máquina virtual, portanto, a única maneira de usá-lo é a biblioteca padrão. Os exemplos são os seguintes:

script {
    use 0x1::Vector;

    fun main() {
        // 使用泛型创建一个空的vector
        let a = Vector::empty<u8>();
        let i = 0;

        // 填充数据
        while (i < 10) {
            Vector::push_back(&mut a, i);
            i = i + 1;
        };

        // 打印vector的长度
        let a_len = Vector::length(&a);
        0x1::Debug::print<u64>(&a_len);

        // 从vector中移除数据
        Vector::pop_back(&mut a);
        Vector::pop_back(&mut a);

        // 重新打印长度
        let a_len = Vector::length(&a);
        0x1::Debug::print<u64>(&a_len);
    }
}

A capacidade máxima que o vetor pode armazenar dados é 18446744073709551615, e também podemos empacotá-lo para facilitar o uso:

module Shelf {

    use 0x1::Vector;

    struct Box<T> {
        value: T
    }

    struct Shelf<T> {
        boxes: vector<Box<T>>
    }

    public fun create_box<T>(value: T): Box<T> {
        Box { value }
    }

    public fun value<T: copy>(box: &Box<T>): T {
        *&box.value
    }

    public fun create<T>(): Shelf<T> {
        Shelf {
            boxes: Vector::empty<Box<T>>()
        }
    }

    public fun put<T>(shelf: &mut Shelf<T>, box: Box<T>) {
        Vector::push_back<Box<T>>(&mut shelf.boxes, box);
    }

    public fun remove<T>(shelf: &mut Shelf<T>): Box<T> {
        Vector::pop_back<Box<T>>(&mut shelf.boxes)
    }

    public fun size<T>(shelf: &Shelf<T>): u64 {
        Vector::length<Box<T>>(&shelf.boxes)
    }
}


Matrizes e strings hexadecimais definidas por vetor embutido

Vetores também podem representar strings. A VM oferece suporte à passagem de vetores como argumentos para funções no script principal. Os vetores também podem ser definidos em scripts ou módulos usando literais hexadecimais

script {

    use 0x1::Vector;

    // 这时main函数接受参数的方式
    fun main(name: vector<u8>) {
        let _ = name;

        
        // 这是 "hello world" 字符串!
        let str = x"68656c6c6f20776f726c64";
    }
}

Uma maneira mais fácil é usar uma string literal:

script {

    fun main() {
        let _ = b"hello world";
    }
}

Eles são tratados como strings ASCII e também interpretados como vetores.

folha de dicas do vetor

Aqui está uma pequena lista de métodos Vector na biblioteca padrão:

Cria um vetor vazio do tipo

Vector::empty<E>(): vector<E>;

obter o comprimento do vetor

Vector::length<E>(v: &vector<E>): u64;

adicione o elemento e ao final do vetor

Vector::push_back<E>(v: &mut vector<E>, e: E);

Obtenha uma referência mutável para os elementos do vetor. Referências imutáveis ​​podem usar Vector::borrow()

Vector::borrow_mut<E>(v: &mut vector<E>, i: u64): &E;

pegue um elemento do final do vetor

Vector::pop_back<E>(v: &mut vector<E>): E;

Recurso

A seguir aprenderemos um conceito muito importante Resource in Move, que torna o Move único, seguro e poderoso.
Primeiro, vamos dar uma olhada nos principais pontos sobre Resource no site do desenvolvedor Diem (a página original foi excluída após a renomeação de Libra para Diem):

A principal função do Move é fornecer um tipo de Recurso personalizado. Os tipos de recursos codificam ativos digitais seguros e fornecem uma programação avançada. Um Recurso é um valor comum na linguagem Move. Eles podem ser armazenados como estruturas de dados, passados ​​como argumentos para funções e retornados de funções.

Resource é uma estrutura especial que pode ser definida e criada no código Move, ou um Resource existente pode ser usado. Portanto, podemos gerenciar ativos digitais como qualquer outro dado, como vetores ou estruturas.

O sistema de tipo de movimento fornece garantias especiais de segurança para o Recurso. O recurso nunca pode ser copiado, reutilizado ou descartado. Um tipo de recurso só pode ser criado ou destruído pelo módulo que o define. Essas verificações são impostas pela máquina virtual Move por meio da verificação de bytecode. O Move VM se recusará a executar qualquer código que não tenha passado pela verificação de bytecode.

signatário

Antes de começarmos a trabalhar com Recursos, precisamos entender o tipo de signatário e por que ele existe.

O signatário é um tipo não copiável semelhante ao recurso nativo que contém o endereço do remetente da transação.
O tipo Signatário representa a autoridade do remetente. Em outras palavras, usar um signatário significa ter acesso ao endereço e recurso do remetente. Não está diretamente relacionado à assinatura, no que diz respeito ao Move VM, significa apenas o remetente.
Signatário tem apenas uma habilidade: Soltar.

assinante do script

Signer é um tipo nativo e deve ser criado antes do uso. Ao contrário de tipos primitivos como vetor, signatário não pode ser criado diretamente no código, mas pode ser passado como um parâmetro de script:

script {
    fun main(account: signer) {
        let _ = account;
    }
}

Parâmetro do signatário Não há necessidade de passá-lo manualmente para o script, o cliente (CLI) o colocará automaticamente em seu script. Além disso, o signatário é apenas uma referência e, embora o valor real do signatário esteja acessível na biblioteca padrão, a função que usa esse valor é privada e não pode usar ou passar o valor do signatário em nenhum outro lugar.

Atualmente, o nome da variável habitual do tipo de signatário é account

O módulo Signer na biblioteca padrão

Os tipos nativos são inseparáveis ​​dos métodos nativos e os métodos nativos do signatário estão incluídos no módulo 0x1::Signer. Este módulo é relativamente simples. Para detalhes, consulte a implementação do módulo Signer na biblioteca padrão Diem:

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)
    }
}

O módulo contém dois métodos, um é um método nativo e o outro é um método Move. Este último é mais conveniente de usar porque usa o operador de acesso para copiar o endereço.

assinante no módulo

module M {
    use 0x1::Signer;

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

Usar &signer como um argumento para uma função indica que a função está usando o endereço do remetente.
Uma das razões para introduzir o tipo de signatário é deixar claro quais funções requerem permissões de remetente e quais não. Portanto, uma função não pode induzir um usuário a obter acesso não autorizado a seu recurso.

afinal

Este artigo apresenta principalmente alguns conceitos básicos relacionados a vetores e recursos na linguagem Move.Para mais artigos, você pode prestar atenção à conta oficial QStack.

Acho que você gosta

Origin blog.csdn.net/QStack/article/details/128944342
Recomendado
Clasificación