Die nächste Generation der intelligenten Vertragsentwicklungssprache Move (7)

Vorwort

Im vorherigen Artikel haben wir hauptsächlich die Generika in der Move-Sprache vorgestellt und etwas über die Definition und Verwendung von Generika gelernt. In Move können Generika für Strukturen und Funktionen verwendet werden. Die Datentypstruktur kann uns dabei helfen, unsere eigenen Typen zu erstellen und komplexe Datenstrukturen zu speichern, aber manchmal benötigen wir flexiblere, skalierbare und verwaltbare Datenstrukturen. Um dieser Nachfrage gerecht zu werden, stellt Move Vector bereit.

Was ist Vektor?

Vector ist ein integrierter Datentyp von Move zum Speichern großer Datenmengen. Dies ist eine Lösung für Sammlungen von Daten aller Art. Seine Funktionen werden von der virtuellen Maschine bereitgestellt, daher ist die einzige Möglichkeit, ihn zu verwenden, die Standardbibliothek. Beispiele sind wie folgt:

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

Die maximale Kapazität, die Vector Daten speichern kann, beträgt 18446744073709551615, und wir können sie auch zur einfachen Verwendung packen:

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


Hex-Arrays und Strings, definiert durch Inline-Vektor

Vektoren können auch Zeichenfolgen darstellen. Die VM unterstützt die Übergabe von Vektoren als Argumente an Funktionen im Hauptskript. Vektoren können auch in Skripten oder Modulen mithilfe hexadezimaler Literale definiert werden

script {

    use 0x1::Vector;

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

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

Eine einfachere Möglichkeit ist die Verwendung eines String-Literals:

script {

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

Sie werden als ASCII-Strings behandelt und auch als Vektoren interpretiert.

Vektor-Spickzettel

Hier ist eine kurze Liste der Vector-Methoden in der Standardbibliothek:

Erstellt einen leeren Vektor vom Typ

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

Ermitteln Sie die Länge des Vektors

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

Fügen Sie das Element e am Ende des Vektors hinzu

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

Erhalten Sie eine veränderliche Referenz auf die Elemente des Vektors. Unveränderliche Referenzen können Vector::borrow() verwenden

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

Nimm ein Element vom Ende des Vektors

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

Ressource

Als nächstes lernen wir eine sehr wichtige Konzeptressource in Move kennen, die Move einzigartig, sicher und leistungsstark macht.
Werfen wir zunächst einen Blick auf die wichtigsten Punkte zu Resource auf der Diem-Entwickler-Website (die Originalseite wurde nach der Umbenennung von Libra in Diem gelöscht):

Die Hauptfunktion von Move besteht darin, einen benutzerdefinierten Ressourcentyp bereitzustellen. Ressourcentypen kodieren sichere digitale Assets und bieten umfassende Programmierbarkeit. Eine Ressource ist ein gewöhnlicher Wert in der Move-Sprache. Sie können als Datenstrukturen gespeichert, als Argumente an Funktionen übergeben und von Funktionen zurückgegeben werden.

Bei einer Ressource handelt es sich um eine spezielle Struktur, die im Move-Code definiert und erstellt werden kann, oder es kann eine vorhandene Ressource verwendet werden. Daher können wir digitale Assets wie alle anderen Daten wie Vektoren oder Strukturen verwalten.

Das Move-Typ-System bietet besondere Sicherheitsgarantien für Resource . Eine Ressource kann niemals kopiert, wiederverwendet oder verworfen werden. Ein Ressourcentyp kann nur von dem Modul erstellt oder zerstört werden, das ihn definiert. Diese Prüfungen werden von der virtuellen Move-Maschine durch Bytecode-Überprüfung erzwungen. Die Move-VM weigert sich, Code auszuführen, der die Bytecode-Überprüfung nicht bestanden hat.

Unterzeichner

Bevor wir mit der Arbeit mit Ressourcen beginnen, müssen wir den Unterzeichnertyp verstehen und wissen, warum er existiert.

Signer ist ein nativer, ressourcenähnlicher, nicht kopierbarer Typ, der die Adresse des Absenders der Transaktion enthält.
Der Unterzeichnertyp repräsentiert die Autorität des Absenders. Mit anderen Worten bedeutet die Verwendung eines Unterzeichners, dass er Zugriff auf die Adresse und Ressource des Absenders hat. Es steht nicht in direktem Zusammenhang mit der Signatur, soweit es die Move VM betrifft, sondern es handelt sich lediglich um den Absender.
Der Unterzeichner hat nur eine Fähigkeit: Drop.

Skriptunterzeichner

Signer ist ein nativer Typ und muss vor der Verwendung erstellt werden. Im Gegensatz zu primitiven Typen wie dem Vektor kann der Unterzeichner nicht direkt im Code erstellt, sondern als Skriptparameter übergeben werden:

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

Unterzeichnerparameter Sie müssen ihn nicht manuell an das Skript übergeben, der Client (CLI) fügt ihn automatisch in Ihr Skript ein. Außerdem ist „signer“ durchgehend nur eine Referenz, und während auf den tatsächlichen Wert von „signer“ in der Standardbibliothek zugegriffen werden kann, ist die Funktion, die diesen Wert verwendet, privat und kann den Wert „signer“ nirgendwo anders verwenden oder übergeben.

Derzeit ist der übliche Variablenname des Unterzeichnertyps „Konto“.

Das Signer-Modul in der Standardbibliothek

Native Typen sind untrennbar mit nativen Methoden verbunden, und die nativen Methoden von signer sind im Modul 0x1::Signer enthalten. Dieses Modul ist relativ einfach. Weitere Informationen finden Sie in der Implementierung des Signer-Moduls in der Diem-Standardbibliothek:

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

Das Modul enthält zwei Methoden, eine ist eine native Methode und die andere ist eine Move-Methode. Letzteres ist bequemer zu verwenden, da es den Zugriffsoperator zum Kopieren der Adresse verwendet.

Unterzeichner im Modul

module M {
    use 0x1::Signer;

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

Die Verwendung von &signer als Argument für eine Funktion zeigt an, dass die Funktion die Adresse des Absenders verwendet.
Einer der Gründe für die Einführung des Unterzeichnertyps besteht darin, klarzustellen, welche Funktionen Absenderberechtigungen erfordern und welche nicht. Daher kann eine Funktion einen Benutzer nicht dazu verleiten, sich unbefugten Zugriff auf ihre Ressource zu verschaffen.

zu guter Letzt

In diesem Artikel werden hauptsächlich einige grundlegende Konzepte im Zusammenhang mit Vektoren und Ressourcen in der Move-Sprache vorgestellt. Weitere Artikel finden Sie im offiziellen QStack-Konto.

Supongo que te gusta

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