# Aleo Instructions Language Guide

### Statically Typedβ

Aleo instructions is a statically typed language, which means we must know the type of each variable before executing a circuit.

### Explicit Types Requiredβ

There is no `undefined` or `null` value in Aleo instructions. When assigning a new variable, the type of the value must be explicitly stated.

### Pass by Valueβ

Expressions in Aleo instructions are always passed by value, which means their values are always copied when they are used as function inputs or in right sides of assignments.

### Register basedβ

There are no variable names in Aleo instructions. All variables are stored in registers denoted `rX` where `X` is a non-negative whole number starting from 0 `r0, r1, r2, etc.`.

## Data Types and Valuesβ

### Booleansβ

Aleo instructions supports the traditional `true` or `false` boolean values. The explicit `boolean` type for booleans in statements is required.

``function main:    input r0: boolean.private;``

### Integersβ

Aleo instructions supports signed integer types `i8`, `i16`, `i32`, `i64`, `i128` and unsigned integer types `u8`, `u16`, `u32`, `u64`, `u128`.

``function main:    input r0: u8.public;``
info

Higher bit length integers generate more constraints in the circuit, which can slow down computation time.

### Field Elementsβ

Aleo instructions supports the `field` type for elements of the base field of the elliptic curve. These are unsigned integers less than the modulus of the base field, so the largest field element is `8444461749428370424248824938781546531375899335154063827935233455917409239040field`.

``function main:    input r0: field.private;``

### Group Elementsβ

The set of affine points on the elliptic curve passed into the Aleo instructions compiler forms a group. The curve is a Twisted Edwards curve with `a = -1` and `d = 3021`. Aleo instructions supports a subgroup of the group, generated by a generator point, as a primitive data type. A group element is denoted by the x-coordinate of its point; for example, `2group` means the point `(2, 5553594316923449299484601589326170487897520766531075014687114064346375156608)`. The generator point is `1540945439182663264862696551825005342995406165131907382295858612069623286213group`.

``function main:    input r0: group.private;``

### Scalar Elementsβ

Aleo instructions supports the `scalar` type for elements of the scalar field defined by the elliptic curve subgroup. These are unsigned integers less than the modulus of the scalar field, so the largest scalar is `2111115437357092606062206234695386632838870926408408195193685246394721360382scalar`.

``function main:    input r0: scalar.private;``

Addresses are defined to enable compiler-optimized routines for parsing and operating over addresses.

``function main:    input r0: address.private;``

### Signaturesβ

Aleo uses a Schnorr signatures scheme to sign messages with an Aleo private key. Signatures can be verified in Aleo instructions using the `sign.verify` instruction.

``sign.verify sign069ju4e8s66unu25celqycvsv3k9chdyz4n4sy62tx6wxj0u25vqp58hgu9hwyqc63qzxvjwesf2wz0krcvvw9kd9x0rsk4lwqn2acqhp9v0pdkhx6gvkanuuwratqmxa3du7l43c05253hhed9eg6ppzzfnjt06fpzp6msekdjxd36smjltndmxjndvv9x2uecsgngcwsc2qkns4afd r1 r2 into r3;``

## Layout of an Aleo Programβ

An Aleo program contains declarations of a Program ID, Imports, Functions, Closures, Structs, Records, Mappings, and Finalize. Ordering is only enforced for imports which must be at the top of file. Declarations are locally accessible within a program file. If you need a declaration from another program file, you must import it.

### Program IDβ

A program ID is declared as `{name}.{network}`. The first character of a `name` must be lowercase. `name` can contain lowercase letters, numbers, and underscores. Currently, `aleo` is the only supported `network` domain.

``program hello.aleo; // validprogram Foo.aleo;   // invalidprogram baR.aleo;   // invalidprogram 0foo.aleo;  // invalidprogram 0_foo.aleo; // invalidprogram _foo.aleo;  // invalid``

### Importβ

An import is declared as `import {ProgramID};`.
Imports fetch other declarations by their program ID and bring them into the current file scope. You can import dependencies that are downloaded to the `imports` directory.

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

### Functionβ

A function is declared as `function {name}:`.
Functions contain instructions that can compute values. Functions must be in a program's current scope to be called.

``function foo:    input r0 as field.public;    input r1 as field.private;    add r0 r1 into r2;    output r2 as field.private;``

#### Function Inputsβ

A function input is declared as `input {register} as {type}.{visibility};`.
Function inputs must be declared just after the function name declaration.

``// The function `foo` takes a single input `r0` with type `field` and visibility `public`.function foo:    input r0 as field.public;``

#### Function Outputsβ

A function output is declared as `output {register} as {type}.{visibility};`.
Function outputs must be declared at the end of the function definition.

``...    output r0 as field.public;``

#### Call a Functionβ

In the Aleo protocol, calling a function creates a transition that can consume and produce records on-chain. Use the `aleo run` CLI command to pass inputs to a function and execute the program.
In Testnet3, program functions cannot call other internal program functions. If you would like to develop "helper functions" that are called internally within a program, try writing a `closure`.

#### Call an Imported Functionβ

Aleo programs can externally call other Aleo programs using the `call {program}/{function} {register} into {register}` instruction.

``import foo.aleo;program bar.aleo;function call_external:    input r0 as u64.private;    call foo.aleo/baz r0 into r1; // Externally call function `baz` in foo.aleo with argument `r0` and store the result in `r1`.    output r1;``

### Closureβ

A closure is declared as `closure {name}:`.
Closures contain instructions that can compute values. Closures are helper functions that cannot be executed directly. Closures may be called by other functions.

``closure foo:    input r0 as field;    input r1 as field;    add r0 r1 into r2;    output r2 as field;``

#### Call a Closureβ

Aleo programs can internally call other Aleo closures using the `call {name} {register} into {register}` instruction.

``program bar.aleo;function call_internal:    input r0 as u64.private;    call foo r0 into r1; // Internally call closure `foo` with argument `r0` and store the result in `r1`.    output r1;``

### Structβ

A struct is a data type declared as `struct {name}:`.
Structs contain component declarations `{name} as {type}`.

``struct array3:    a0 as u32;    a1 as u32;    a2 as u32;``

To instantiate a `struct` in a program use the `cast` instruction.

``function new_array3:    input r0 as u32.private;    input r1 as u32.private;    input r2 as u32.private;    cast r0 r1 r2 into r3 as array3;    output r3;``

### Arrayβ

An array is a data type declared as `[{value}, {value}]`.

``[true, false, true]``

Arrays contain a list of values of the same type `[{type}; {length}]`.

``[boolean; 3u32]``

Arrays can be initialized using the `cast` opcode.

``function new_array:    input r0 as boolean.private;    input r1 as boolean.private;    input r2 as boolean.private;    cast r0 r1 r2 into r3 as [boolean; 3u32];    output r3;``

Arrays can be indexed using `{name}[{index}]`.

``function get_array_element:    input r0 as [boolean; 4u32].public;    input r1 as u32.public;    r0[r1] into r2;    output r2;``

Arrays can be nested.

``[[true, false, true, false], [false, true, false, true]]``
``function get_nested_array_element:    input r0 as [[boolean; 4u32]; 2u32].public;    r0[0u32][1u32] into r1;    output r1;``
info

Aleo instructions currently only support fixed-length static arrays.

### Recordβ

A record type is declared as `record {name}:`.
Records contain component declarations `{name} as {type}.{visibility};`.
Record data structures must contain the `owner` declaration as shown below.
When passing a record as input to a program function the `_nonce as group.{visibility}` declaration is also required.

``record token:    // The token owner.    owner as address.private;    // The token amount.    amount as u64.private;``

To instantiate a `record` in a program use the `cast` instruction.

``function new_token:    input r0 as address.private;    input r1 as u64.private;    input r2 as u64.private;    cast r0 r1 r2 into r3 as token.record;    output r3;``

### Mappingβ

A mapping is declared as `mapping {name}:`.
Mappings contain key-value pairs. Mappings must be defined within a program scope. Mappings are stored publicly on-chain. It is not possible to store data privately in a mapping.

``// On-chain storage of an `account` map, with `owner` as the key,// and `amount` as the value.mapping account:    // The token owner.    key owner as address.public;    // The token amount.    value amount as u64.public;``

#### Containsβ

A contains command that checks if a key exists in a mapping, e.g. `contains accounts[r0] into r1;`.

#### Getβ

A get command that retrieves a value from a mapping, e.g. `get accounts[r0] into r1;`.

#### Get or Useβ

A get command that uses the provided default in case of failure, e.g. `get.or_use accounts[r0] r1 into r2;`.

``finalize transfer_public:    // Input the sender.    input r0 as address.public;    // Input the receiver.    input r1 as address.public;    // Input the amount.    input r2 as u64.public;    // Decrements `account[r0]` by `r2`.    // If `account[r0]` does not exist, 0u64 is used.    // If `account[r0] - r2` underflows, `transfer_public` is reverted.    get.or_use account[r0] 0u64 into r3;    sub r3 r2 into r4;    set r4 into account[r0];    // Increments `account[r1]` by `r2`.    // If `account[r1]` does not exist, 0u64 is used.    // If `account[r1] + r2` overflows, `transfer_public` is reverted.    get.or_use account[r1] 0u64 into r5;    add r5 r2 into r6;    set r6 into account[r1];``

#### Setβ

A set command that sets a value in a mapping, e.g. `set r0 into accounts[r0];`.

#### Removeβ

A remove command that removes a key-value pair from a mapping, e.g. `remove accounts[r0];`.

### Finalizeβ

A finalize is declared as `finalize {name}:`.
A finalize must immediately follow a function, and must have the same name;

``// The `transfer_public_to_private` function turns a specified amount// from the mapping `account` into a record for the specified receiver.//// This function preserves privacy for the receiver's record, however// it publicly reveals the sender and the specified amount.function transfer_public_to_private:    // Input the receiver.    input r0 as address.public;    // Input the amount.    input r1 as u64.public;    // Construct a record for the receiver.    cast r0 r1 into r2 as credits.record;    // Decrement the balance of the sender publicly.    async transfer_public_to_private self.caller r1 into r3;        // Output the record of the receiver.    output r2 as credits.record;        // Output the future of the decrement operation.    output r3 as token.aleo/transfer_public_to_private.future;    finalize transfer_public_to_private:    // Input the sender.    input r0 as address.public;    // Input the amount.    input r1 as u64.public;    // Retrieve the balance of the sender.    // If `account[r0]` does not exist, 0u64 is used.    get.or_use account[r0] 0u64 into r2;    // Decrements `account[r0]` by `r1`.    // If `r2 - r1` underflows, `trasfer_public_to_private` is reverted.    sub r2 r1 into r3;    // Updates the balance of the sender.    set r3 into account[r0];``
note

Previously, a `finalize` function was executed on chain after the zero-knowledge proof of the execution of the associated function is verified; Upon success of the finalize function, the program logic was executed.
Upon failure of the finalize function, the program logic was reverted.

### Futuresβ

A future is equivalent to the call graph of the on-chain execution and is explicitly used when finalizing an execution. Instead of constructing the call graph implicitly from the code, the transition/circuit explicitly outputs a future, specifying which code blocks to run on-chain and how to run them.

#### future typeβ

A user can declare a future type by specifying a `Locator` followed by the tag `.future`. For example, `credits.aleo/mint_public.future`. A `function` can only output a future and a finalize block can only take a future in as input. A `closure` cannot output a future or take a future in as input.

#### async callβ

A user can make an asynchronous call to the finalize block via the `async` keyword. For example, `async mint_public r0 r1 into r2;`. Note that the associated function must be specified. This operation produces a `Future` as output. `async` takes the place of the `finalize` command, which was allowed in the body of a function after the output statements.

#### await commandβ

A user can evaluate a future inside of a finalize block using the `await` command. For example, `await r0;`. An `await` command can only be used in a finalize block. The operand must be a register containing a Future.

#### Indexing a future.β

A register containing a future can be indexed using the existing index syntax. For example, `r0[0u32]`. This would get the input of the future at that specific index. Accesses can be nested to match the nested structure of a future.

#### Future exampleβ

``program basic_math.aleo;mapping uses:    key user as address.public;    value count as i64.public;function add_and_count:    input r0 as i64.private;    input r1 as i64.private;    add r0 r1 into r2;    async add_and_count self.caller into r3;    output r2 as i64.private;    output r3 as basic_math.aleo/add_and_count.future;finalize add_and_count:    input r0 as address.public;    get.or_use uses[r0] 0i64 into r1;    add r1 1i64 into r2;    set r2 into uses[r0];function sub_and_count:    input r0 as i64.private;    input r1 as i64.private;    sub r0 r1 into r2;    async sub_and_count self.caller into r3;    output r2 as i64.private;    output r3 as basic_math.aleo/sub_and_count.future;finalize sub_and_count:    input r0 as address.public;    get.or_use uses[r0] 0i64 into r1;    add r1 1i64 into r2;    set r2 into uses[r0];/////////////////////////////////////////////////import basic_math.aleo;program count_usages.aleo;function add_and_subtract:    input r0 as i64.private;    input r1 as i64.private;    call basic_math.aleo/add_and_count r0 r1 into r2 r3;    call basic_math.aleo/sub_and_count r2 r1 into r4 r5;    assert.eq r0 r4;    assert.eq r3[0u32] r5[0u32];    async add_and_subtract r3 r5 into r6;    output r0 as i64.private;    output r6 as count_usages.aleo/add_and_subtract.future;finalize add_and_subtract:    input r0 as basic_math.aleo/add_and_count.future;    input r1 as basic_math.aleo/sub_and_count.future;    await r0;    assert.eq r0[0u32] r1[0u32];    await r1;``

There are a number of rules associated with using these components.

1. If a function has a finalize block, it must have exactly one async instruction.
2. If a function has a finalize block, it's last output must be a future.
3. If a function does not have a finalize block, it cannot have an async instruction`.
4. All futures created by calls need to be input to the async instruction in the order they were produced.
5. An async call must reference the same function.
6. All calls must be made before invoking async.
7. The input futures types in a finalize block must match the order in which they were created in the function.
8. All futures in a finalize must be await-ed and in the order in which they were specified.
9. Instructions can be interleaved between invocations of call, async, and await.

### Finalize Commandsβ

The following commands are supported in Aleo Instructions to provide additional program functionality.

#### block.heightβ

The `block.height` command returns the height of the block in which the program is executed (latest block height + 1). This can be useful for managing time-based access control to a program. The `block.height` command must be called within a finalize block.

``assert.eq block.height 100u64;``

#### rand.chachaβ

The `rand.chacha` command returns a random number generated by the ChaCha20 algorithm.
This command supports sampling a random `address`, `boolean`, `field`, `group`, `i8`, `i16`, `i32`, `i64`, `i128`, `u8`, `u16`, `u32`, `u64`, `u128`, and `scalar`.
Up to two additional seeds can be provided to the `rand.chacha` command.
Currently, only ChaCha20 is supported, however, in the future, other random number generators may be supported.

``rand.chacha into r0 as field;rand.chacha r0 into r1 as field;rand.chacha r0 r1 into r2 as field;``

#### Hashβ

Aleo Instructions supports the following syntax for hashing to standard types.

``hash.bhp256 r0 into r1 as address;hash.bhp256 r0 into r1 as field;hash.bhp256 r0 into r1 as group;hash.bhp256 r0 into r1 as i8;hash.bhp256 r0 into r1 as i16;hash.bhp256 r0 into r1 as i32;hash.bhp256 r0 into r1 as i64;hash.bhp256 r0 into r1 as i128;hash.bhp256 r0 into r1 as u8;hash.bhp256 r0 into r1 as u16;hash.bhp256 r0 into r1 as u32;hash.bhp256 r0 into r1 as u64;hash.bhp256 r0 into r1 as u128;hash.bhp256 r0 into r1 as scalar;hash.bhp512 ...;hash.bhp768 ...;hash.bhp1024 ...;hash.ped64 ...;hash.ped128 ...;hash.psd2 ...;hash.psd4 ...;hash.psd8 ...;``

Checkout the Aleo Instructions opcodes for a full list of supported hashing algorithms.

#### Commitβ

Aleo Instructions supports the following syntax for committing to standard types.
Note that the `commit` command requires any type as the first argument, and a `scalar` as the second argument.

``commit.bhp256 r0 r1 into r2 as address;commit.bhp256 r0 r1 into r2 as field;commit.bhp256 r0 r1 into r2 as group;commit.bhp512 ...;commit.bhp768 ...;commit.bhp1024 ...;commit.ped64 ...;commit.ped128 ...;``

Checkout the Aleo Instructions opcodes for a full list of supported commitment algorithms.

#### position, branch.eq, branch.neqβ

The `position` command, e.g. `position exit`, indicates a point to branch execution to.
The `branch.eq` command, e.g. `branch.eq r0 r1 to exit`, which branches execution to the position indicated by `exit` if `r0` and `r1` are equal.
The `branch.neq` command, e.g. `branch.neq r0 r1 to exit`, which branches execution to the position indicated by `exit` if `r0` and `r1` are not equal.

Example The finalize block exits successfully if the input is 0u8 and fails otherwise.

``program test_branch.aleo;function run_test:    input r0 as u8.public;    finalize r0;finalize run_test:    input r0 as u8.public;    branch.eq r0 0u8 to exit;    assert.eq true false;    position exit;``

#### self.signerβ

The `self.signer` command returns the user address that originated the transition. This can be useful for managing access control to a program. In the above example, the `transfer_public_to_private` function decrements the balance of the sender publicly using `self.signer`.

#### self.callerβ

The `self.caller` command returns the address of the immediate caller of the program.

### Program Interoperabilityβ

The examples in this section will use the following environment.

.env
``NETWORK=testnet3PRIVATE_KEY=APrivateKey1zkpE37QxQynZuEGg3XxYrTuvhzWbkVaN5NgzCdEGzS43Ms5 # user private keyADDRESS=aleo1p2h0p8mr2pwrvd0llf2rz6gvtunya8alc49xldr8ajmk3p2c0sqs4fl5mm # user address``

#### Child and Parent Programβ

The following example demonstrates how a program `parent.aleo` can call another program `child.aleo`.

./imports/child.aleo
``program child.aleo;function foo:    output self.caller as address.public;    output self.signer as address.public;``
./parent.aleo
``import child.aleo;program parent.aleo;// Make an external program call from `parent.aleo` to `function foo` in `child.aleo`.function foo:    call child.aleo/foo into r0 r1;    output r0 as address.public;    output r1 as address.public;    output self.caller as address.public;    output self.signer as address.public;``
``\$ snarkvm execute fooβ  Constraints β’  'test.aleo/foo' - 2,025 constraints (called 1 time) β’  'child.aleo/foo' - 0 constraints (called 1 time)β‘οΈ  Outputs # The address of the caller of `child.aleo/foo` => `program.aleo` β’ aleo18tpu6k9g6yvp7uudmee954vgsvffcegzez4y8v8pru0m6k6zdsqqw6mx3t   # The address that originated the sequence of calls leading up to `child.aleo/foo` => user address β’ aleo1p2h0p8mr2pwrvd0llf2rz6gvtunya8alc49xldr8ajmk3p2c0sqs4fl5mm  # The address of the caller of `program.aleo/foo` => user address β’ aleo1p2h0p8mr2pwrvd0llf2rz6gvtunya8alc49xldr8ajmk3p2c0sqs4fl5mm  # The address that originated the sequence of calls leading up to `program.aleo/foo` => user address β’ aleo1p2h0p8mr2pwrvd0llf2rz6gvtunya8alc49xldr8ajmk3p2c0sqs4fl5mm``

#### User Callable Programβ

By `asserting assert.eq self.caller self.signer;` on line 4, a developer can restrict their function such that it can only be called by users.

./imports/child.aleo
``program child.aleo;function foo:    assert.eq self.caller self.signer; // This check should fail if called by another program.    output self.caller as address.public;    output self.signer as address.public;``
./parent.aleo
``import child.aleo;program parent.aleo;// Make an external program call from `parent.aleo` to `function foo` in `child.aleo`.function foo:    call child.aleo/foo into r0 r1;    output r0 as address.public;    output r1 as address.public;    output self.caller as address.public;    output self.signer as address.public;``
``\$ snarkvm execute fooβ οΈ  Failed to evaluate instruction (call child.aleo/foo into r0 r1;):Failed to evaluate instruction (assert.eq self.caller self.signer ;):'assert.eq' failed: 'aleo18tpu6k9g6yvp7uudmee954vgsvffcegzez4y8v8pru0m6k6zdsqqw6mx3t' is not equal to 'aleo1p2h0p8mr2pwrvd0llf2rz6gvtunya8alc49xldr8ajmk3p2c0sqs4fl5mm' (should be equal)``

#### Program Callable Programβ

By asserting `assert.neq self.caller self.signer;` on line 4, a developer can restrict their function such that it can only be called by other programs.

restrict.aleo
``program restrict.aleo;function foo:    assert.neq self.caller self.signer;     output self.caller as address.public;    output self.signer as address.public;``
``\$ snarkvm execute fooβ οΈ  Failed to evaluate instruction (assert.neq self.caller self.signer ;):'assert.neq' failed: 'aleo1p2h0p8mr2pwrvd0llf2rz6gvtunya8alc49xldr8ajmk3p2c0sqs4fl5mm'is equal to 'aleo1p2h0p8mr2pwrvd0llf2rz6gvtunya8alc49xldr8ajmk3p2c0sqs4fl5mm'(should not be equal)``