Skip to content

Releases: ProvableHQ/leo

v1.9.2

08 Aug 18:32
Compare
Choose a tag to compare
commit example files

v1.9.1

24 Jul 18:09
Compare
Choose a tag to compare
chore(leo): bump version for new release

v1.9.0

20 Jul 01:57
Compare
Choose a tag to compare
chore(leo): bump version for new release

v1.8.3

06 Jul 04:43
Compare
Choose a tag to compare
chore(leo): bump version for new release

v1.8.2

29 Jun 04:26
Compare
Choose a tag to compare
chore(leo): bump version for new release

v1.8.1

24 Jun 00:35
Compare
Choose a tag to compare
chore(leo): bump version for new release

v1.8.0

16 Jun 05:53
Compare
Choose a tag to compare
chore(leo): bump version for new release

v1.7.2

01 Jun 03:53
Compare
Choose a tag to compare
chore(leo): bump version for new release

v1.7.1

23 May 22:21
Compare
Choose a tag to compare

Record refactors

Records in Aleo no longer require the gates field.

“gates” is allowed as a standard field of a record to ensure backwards compatibility.

  • Remove gates from tests
  • Remove gates from examples
  • Remove gates from compiler

Expanded programmability

    /// The maximum number of mappings in a program.
    const MAX_MAPPINGS: usize = 31;
    /// The maximum number of functions in a program.
    const MAX_FUNCTIONS: usize = 31;
    /// The maximum number of operands in an instruction.
    const MAX_OPERANDS: usize = Self::MAX_INPUTS;
    /// The maximum number of instructions in a closure or function.
    const MAX_INSTRUCTIONS: usize = u16::MAX as usize;
    /// The maximum number of commands in finalize.
    const MAX_COMMANDS: usize = u16::MAX as usize;

    /// The maximum number of inputs per transition.
    const MAX_INPUTS: usize = 16;
    /// The maximum number of outputs per transition.
    const MAX_OUTPUTS: usize = 16;

v1.7.0

20 Apr 01:22
Compare
Choose a tag to compare

Changes

New Syntax - Mapping and finalize

The syntax around mappings and finalize has been updated to support get, get_or_init, set functions.

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_init(counter, addr, 0u64);
        Mapping::set(counter, addr, current_value + 1u64);
        current_value = Mapping::get(counter, addr);
        Mapping::set(counter, addr, current_value + 1u64);
    }

}

Mapping

The mapping struct allows the programmer to apply updates to a program mapping data structure by calling one of the following functions.

get

A get command, e.g. current_value = Mapping::get(counter, addr);
Gets the value stored at addr in counter and stores the result in current_value
If the value at addr does not exist, then the program will fail to execute.

get_or_init

A get command that initializes the mapping in case of failure, e.g.
let current_value: u64 = Mapping::get_or_init(counter, addr, 0u64);
Gets the value stored at addr in counter and stores the result in current_value.
If the key is not present, 0u64 is stored in counter and stored in current_value.

set

A set command, e.g. Mapping::set(counter, addr, current_value + 1u64);
Sets the addr entry as current_value + 1u64 in counter.

Deprecated Syntax

increment

The increment function has been removed from Leo syntax.
Developers can increment values in a mapping using set

decrement

The decrement function has been removed from Leo syntax.
Developers can decrement values in a mapping using set

New Syntax - Inlined Functions

Users can specify inlined functions in the following way:

inline foo(a: u8, b: u8) -> u8 { ... }

With this new addition, the rules for functions (in the traditional sense) are as follows:

  • There are three variants of functions: transition, function, inline.
  • transitions can only call functions and inlines.
  • functions can only call inlines.
  • inlines can only call inlines.
  • Direct/indirect recursive calls are not allowed

New Optimization - Dead Code Elimination

Dead Code Elimination (DCE) - The Leo compiler will identify and remove unused code blocks in programs - simplifying the generated zk circuit and saving the programmer credits for every execution.
Lets look at DCE in action. Consider the following Leo program and its generated bytecode.

program test.aleo {
    record dummy {
        owner: address,
        gates: u64,
        data: u8,
   

    inline inline_and_eliminate(a: u8, b: u8) -> u8 {
        return a * b;
    }

    transition foo(a: u8, b: u8) -> u8 {
        let c: u8 = a + b;
        let d: u8 = 0u8;
        if (a == b) {
            d = inline_and_eliminate(a, b);
        }
        let e: dummy = dummy {
            owner: self.caller,
            gates: 0u64,
            data: d,
        };
        return a + b;
    }
}

Initial Leo program above.

program test.aleo;

record dummy:
    owner as address.private;
    gates as u64.private;
    data as u8.private;

function foo:
    input r0 as u8.private;
    input r1 as u8.private;
    add r0 r1 into r2;
    output r2 as u8.private;

Compiled bytecode above.

Observation One

Observe that the inline function inline_and_eliminate is not produced in the compiled bytecode. Under the hood, Leo substitutes the code directly from inline_and_eliminate into the transition function foo where it is used. After the code is substituted, the inline function can be removed from the program tree.

Observation Two

Observe that the variables d, e, and the Leo code computing their values are not produced in the compiled bytecode. Leo’s DCE optimization has been hard at work recognizing that the if conditional, the inline function and the record creation are not output by the transition function foo. The last line of the initial program return a + b is the only computation executed by foo. All other code is unnecessary computation in the program and marked as “dead”. Leo will remove the dead code from the program tree before the resulting bytecode is generated.

Bug fixes