认识Leo的语法之Layout概述

今天我们来了解Aleo Leo程序的组成,探索它们的结构元素,并深入研究它们为区块链开发带来的优势。

Leo 程序由程序范围常量importstransition函数辅助函数结构记录映射Finalize 函数组成。文件声明可以在当前文件中访问。如果您需要使用另一个 Leo 文件,则必须导入它。

Aleo Leo程序布局的优势:

  1. 结构清晰: 有组织的结构增强了代码的可读性和理解性。

  2. **模块化设计:**声明被划分,促进模块化开发和代码重用。

  3. 隐私保证: Leo 的可见性选项允许对数据暴露进行细粒度控制。

  4. **链上控制:**最终确定函数为链上状态突变提供了安全机制。

程序范围

Leo 上的程序范围是指驻留在 Aleo 区块链上特定程序 ID 处的代码和数据的关系。它封装了映射、记录、结构、转换函数、辅助函数和finalize 函数。,如下:

import foo.leo;

program hello.aleo {
    mapping balances: address => u64;

    record token {
        owner: address,
        amount: u64,
    }

    struct message {
        sender: address,
        object: u64,
    }

    transition mint_public(
        public receiver: address,
        public amount: u64,
    ) -> token {
        return token {
            owner: receiver,
            amount,
        } then finalize(receiver, amount);
    }

    finalize mint_public(
        public receiver: address,
        public amount: u64,
    ) {
        let current_amount: u64 = Mapping::get_or_use(account, receiver, 0u64);
        Mapping::set(account, receiver, current_amount + amount);
   }

    function compute(a: u64, b: u64) -> u64 {
        return a + b;
    }
}

常量

常量是不可变的值,必须在声明时赋值。它们可以全局定义或在函数范围内定义。

program foo.aleo {
    const FOO: u8 = 1u8;
    
    function bar() -> u8 {
        const BAR: u8 = 2u8;
        return FOO + BAR;
    }
}

Import

Import 有助于将外部声明包含到当前文件中。

import foo.leo; // Import all `foo.leo` declarations into the `hello.aleo` program.

program hello.aleo { }

Struct

Struct 数据类型声明为struct {name} {}.结构体包含组件声明{name}: {type}

struct array3 {
    a0: u32,
    a1: u32,
    a2: u32,
}

Record

记录与 Struct 类似,保存数据组件,但增加了可见性选项 - 常量、公共或私有。

record token {
    // The token owner.
    owner: address,
    // The token amount.
    amount: u64,
}

Arrays, Tuples

Leo 支持静态数组、元组及其组合。这些数据结构可以在您的程序中灵活使用。

// Initalize a boolean array of length 4
let arr: [bool; 4] = [true, false, true, false];

// Nested Array
let nested: [[bool; 2]; 2] = [[true, false], [true, false]];

// Array of Structs
struct bar {
    data: u8,
}

let arr_of_structs: [bar; 2] = [bar { data: 1u8 }, bar { data: 2u8 }];

// Access the field of a struct within an array
transition foo(a: [bar; 8]) -> u8 {
    return a[0u8].data;
}

// Struct that contains an array
struct bat {
    data: [u8; 8],
}

// Record that contains an array
record floo {
    owner: address,
    data: [u8; 8],
}

// Declare a mapping that contains an array value
mapping data: address => [bool; 8];

// Iterate over an array using a for loop and sum the values within
transition sum_with_loop(a: [u64; 4]) -> u64 {
    let sum: u64 = 0u64;
    for i: u8 in 0u8..4u8 {
        sum += a[i];
    }
    return sum;
}

transition函数

transition 函数是 Leo 计划的核心。它们计算值并且必须在当前程序范围内。

program test.aleo {
    transition baz(foo: u8, bar: u8) -> u8 {
        let a: (u8, u8) = (foo, bar);
        let result: u8 = a.0 + a.1;
        return result;
    }
}

辅助函数

辅助函数包含用于内部计算的表达式和语句。它们不能生成记录并由其他函数调用。

function foo(
    a: field,
    b: field,
) -> field {
    return a + b;
}

内联函数

内联函数被声明为inline {name}() {}.内联函数包含可以计算值的表达式和语句。内联函数不能直接从外部执行,而是 Leo 编译器在每个调用点内联函数体。

inline foo(
    a: field,
    b: field,
) -> field {
    return a + b;
}

Finalize 函数

Finalize 函数被声明为finalize {name}:并用于在链上运行计算。其主要目的之一是启动或更改映射内的公共链状态。

program transfer.aleo {
    // The function `transfer_public_to_private` turns a specified token amount
    // from `account` into a token record for the specified receiver.
    //
    // This function preserves privacy for the receiver's record, however
    // it publicly reveals the caller and the specified token amount.
    transition transfer_public_to_private(
        public receiver: address,
        public amount: u64
    ) -> token {
        // Produce a token record for the token receiver.
        let new: token = token {
            owner: receiver,
            amount,
        };

        // Return the receiver's record, then decrement the token amount of the caller publicly.
        return new then finalize(self.caller, amount);
    }

    finalize transfer_public_to_private(
        public sender: address,
        public amount: u64
    ) {
        // Decrements `account[sender]` by `amount`.
        // If `account[sender]` does not exist, it will be created.
        // If `account[sender] - amount` underflows, `transfer_public_to_private` is reverted.
        let current_amount: u64 = Mapping::get_or_use(account, sender, 0u64);
        Mapping::set(account, sender, current_amount - amount);
    }
}

Mapping

Mapping 被声明为mapping {name}: {key-type} => {value-type}.映射包含键值对,映射存储在链上。

// On-chain storage of an `account` mapping,
// with `address` as the type of keys,
// and `u64` as the type of values.
mapping account: address => u64;

Mapping 允许程序员通过调用以下函数之一来对程序映射数据结构应用更新

program test.aleo {
    mapping counter: address => u64;

    transition dubble() {
        return then finalize(self.caller);
    }

    finalize dubble(addr: address) {
        let current_value: u64 = Mapping::get_or_use(counter, addr, 0u64);
        Mapping::set(counter, addr, current_value + 1u64);
        current_value = Mapping::get(counter, addr);
        Mapping::set(counter, addr, current_value + 1u64);
    }

}

For 循环

For 循环声明为for {variable: type} in {lower bound}..{upper bound}.建议将无符号整数类型u8u16、 和作为循环变量类型。u32下限必须小于上限,支持嵌套循环。

  let count: u32 = 0u32;

  for i: u32 in 0u32..5u32 {
    count += 1u32;
  }

  return count; // returns 5u32

总之,Aleo Leo 定义明确的程序结构和强大的功能使开发人员能够构建复杂且以隐私为中心的区块链应用程序。