Skip to content

Commit

Permalink
[Feature] Implement leo execute (#2491)
Browse files Browse the repository at this point in the history
* bump snarkvm rev

* update default gitignore

* impl leo execute

* bump snarkvm 0.14.5

* modify examples wip

* update run.sh examples

* impl env file

* clippy warning

* fix auction example

* fix auction example env

* generate new private key for new env - tests failing due to env not found err

* commit error changes

* Fix tests; clippy

* Get examples working

* leo build checks that build dir is well formed; clippy

* Clean up

* Update examples/README.md

Co-authored-by: d0cd <pranavsaig@gmail.com>
Signed-off-by: Collin Chin <16715212+collinc97@users.noreply.github.com>

* do not commit .avm files

* use snarkvm commands

---------

Signed-off-by: Collin Chin <16715212+collinc97@users.noreply.github.com>
Co-authored-by: Pranav Gaddamadugu <pranav@aleo.org>
Co-authored-by: d0cd <pranavsaig@gmail.com>
  • Loading branch information
3 people authored Jul 20, 2023
1 parent 24248c3 commit d44457f
Show file tree
Hide file tree
Showing 175 changed files with 11,596 additions and 806 deletions.
683 changes: 387 additions & 296 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ members = [
]

[workspace.dependencies.snarkvm]
version = "0.12.6"
version = "=0.14.5"

[workspace.dependencies.snarkvm-console]
version = "0.12.3"
version = "=0.14.5"

[lib]
path = "leo/lib.rs"
Expand Down
9 changes: 8 additions & 1 deletion compiler/compiler/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,14 @@ version = "0.10"

[dev-dependencies.leo-test-framework]
path = "../../tests/test-framework"
version = "1.4.0"
version = "1.8.3"

[dev-dependencies.leo-package]
path = "../../leo/package"
version = "1.8.3"

[dev-dependencies.dotenvy]
version = "0.15.7"

[dev-dependencies.rand]
version = "0.8"
Expand Down
1 change: 1 addition & 0 deletions compiler/compiler/tests/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ fn run_test(test: Test, handler: &Handler, buf: &BufferEmitter) -> Result<Value,
let bytecode = handler.extend_if_error(compile_and_process(&mut parsed))?;

// Set up the build directory.
// Note that this function checks that the bytecode is well-formed.
let package = setup_build_directory(&program_name, &bytecode, handler)?;

// Get the program process and check all instructions.
Expand Down
4 changes: 2 additions & 2 deletions compiler/compiler/tests/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ mod utilities;
use utilities::{
buffer_if_err,
compile_and_process,
dotenv_private_key,
get_build_options,
get_cwd_option,
hash_asts,
Expand Down Expand Up @@ -152,8 +153,7 @@ fn run_test(test: Test, handler: &Handler, err_buf: &BufferEmitter) -> Result<Va
// TODO: Add support for custom config like custom private keys.
// Execute the program and get the outputs.
let output_string = match package.run::<Aleo, _>(
None,
package.manifest_file().development_private_key(),
&dotenv_private_key(package.directory()).unwrap(),
function_name,
&inputs,
rng,
Expand Down
23 changes: 20 additions & 3 deletions compiler/compiler/tests/utilities/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ use leo_errors::{
LeoError,
LeoWarning,
};
use leo_package::root::env::Env;
use leo_passes::{CodeGenerator, Pass};
use leo_span::source_map::FileName;
use leo_test_framework::Test;
use leo_test_framework::{test::TestConfig, Test};

use snarkvm::prelude::*;

use leo_test_framework::test::TestConfig;
use snarkvm::{file::Manifest, package::Package};
use std::{
cell::RefCell,
Expand Down Expand Up @@ -109,12 +109,18 @@ pub fn setup_build_directory(program_name: &str, bytecode: &String, handler: &Ha
// Create the manifest file.
let _manifest_file = Manifest::create(&directory, &program_id).unwrap();

// Create the environment file.
Env::<Network>::new().write_to(&directory).unwrap();
if Env::<Network>::exists_at(&directory) {
println!(".env file created at {:?}", &directory);
}

// Create the build directory.
let build_directory = directory.join("build");
fs::create_dir_all(build_directory).unwrap();

// Open the package at the temporary directory.
handler.extend_if_error(Package::<Testnet3>::open(&directory).map_err(LeoError::Anyhow))
handler.extend_if_error(Package::<Network>::open(&directory).map_err(LeoError::Anyhow))
}

pub fn new_compiler(
Expand Down Expand Up @@ -222,3 +228,14 @@ pub fn compile_and_process<'a>(parsed: &'a mut Compiler<'a>) -> Result<String, L

Ok(bytecode)
}

/// Returns the private key from the .env file specified in the directory.
#[allow(unused)]
pub fn dotenv_private_key(directory: &Path) -> Result<PrivateKey<Network>> {
use std::str::FromStr;
dotenvy::from_path(directory.join(".env")).map_err(|_| anyhow!("Missing a '.env' file in the test directory."))?;
// Load the private key from the environment.
let private_key = dotenvy::var("PRIVATE_KEY").map_err(|e| anyhow!("Missing PRIVATE_KEY - {e}"))?;
// Parse the private key.
PrivateKey::<Network>::from_str(&private_key)
}
2 changes: 1 addition & 1 deletion compiler/passes/src/code_generation/visit_expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ impl<'a> CodeGenerator<'a> {
Expression::Identifier(identifier) => identifier.name,
_ => unreachable!("Parsing guarantees that all `input.function` is always an identifier."),
};
let return_type = &self.symbol_table.borrow().functions.get(&function_name).unwrap().output_type;
let return_type = &self.symbol_table.borrow().lookup_fn_symbol(function_name).unwrap().output_type;
match return_type {
Type::Unit => {
call_instruction.push(';');
Expand Down
6 changes: 3 additions & 3 deletions compiler/passes/src/flattening/flatten_statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ impl StatementReconstructor for Flattener<'_> {
_ => unreachable!("Parsing guarantees that `function` is an identifier."),
};

let function = self.symbol_table.borrow().functions.get(&function_name).unwrap();
let function = self.symbol_table.borrow().lookup_fn_symbol(function_name).unwrap();
match &function.output_type {
// If the function returns a tuple, reconstruct the assignment and add an entry to `self.tuples`.
Type::Tuple(tuple) => {
Expand Down Expand Up @@ -246,7 +246,7 @@ impl StatementReconstructor for Flattener<'_> {
Expression::Identifier(identifier) => {
// Retrieve the entry in the symbol table for the mapping.
// Note that this unwrap is safe since type checking ensures that the mapping exists.
let variable = self.symbol_table.borrow().variables.get(&identifier.name).unwrap();
let variable = self.symbol_table.borrow().lookup_variable(identifier.name).unwrap();
match &variable.type_ {
Type::Mapping(mapping_type) => &*mapping_type.value,
_ => unreachable!("Type checking guarantee that `arguments[0]` is a mapping."),
Expand Down Expand Up @@ -281,7 +281,7 @@ impl StatementReconstructor for Flattener<'_> {
_ => unreachable!("Parsing guarantees that `function` is an identifier."),
};

let function = self.symbol_table.borrow().functions.get(&function_name).unwrap();
let function = self.symbol_table.borrow().lookup_fn_symbol(function_name).unwrap();

let output_type = match &function.output_type {
Type::Tuple(tuple) => tuple.clone(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ impl ExpressionConsumer for StaticSingleAssigner<'_> {

// Lookup the struct definition.
// Note that type checking guarantees that the correct struct definition exists.
let struct_definition: &Struct = self.symbol_table.borrow().structs.get(&input.name.name).unwrap();
let struct_definition: &Struct = self.symbol_table.borrow().lookup_struct(input.name.name).unwrap();

// Initialize the list of reordered members.
let mut reordered_members = Vec::with_capacity(members.len());
Expand Down
50 changes: 32 additions & 18 deletions errors/src/errors/cli/cli_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,65 +89,79 @@ create_messages!(
}

@backtraced
failed_to_execute_aleo_build {
failed_to_execute_build {
args: (error: impl Display),
msg: format!("Failed to execute the `aleo build` command.\nSnarkVM Error: {error}"),
msg: format!("Failed to execute the `build` command.\nSnarkVM Error: {error}"),
help: None,
}

@backtraced
failed_to_execute_aleo_new {
failed_to_execute_new {
args: (error: impl Display),
msg: format!("Failed to execute the `aleo new` command.\nSnarkVM Error: {error}"),
msg: format!("Failed to execute the `new` command.\nSnarkVM Error: {error}"),
help: None,
}

@backtraced
failed_to_execute_aleo_run {
failed_to_execute_run {
args: (error: impl Display),
msg: format!("Failed to execute the `aleo run` command.\nSnarkVM Error: {error}"),
msg: format!("Failed to execute the `run` command.\nSnarkVM Error: {error}"),
help: None,
}

@backtraced
failed_to_execute_aleo_node {
failed_to_execute_node {
args: (error: impl Display),
msg: format!("Failed to execute the `aleo node` command.\nSnarkVM Error: {error}"),
msg: format!("Failed to execute the `node` command.\nSnarkVM Error: {error}"),
help: None,
}

@backtraced
failed_to_execute_aleo_deploy {
failed_to_execute_deploy {
args: (error: impl Display),
msg: format!("Failed to execute the `aleo deploy` command.\nSnarkVM Error: {error}"),
msg: format!("Failed to execute the `deploy` command.\nSnarkVM Error: {error}"),
help: None,
}

@backtraced
failed_to_parse_aleo_new {
failed_to_parse_new {
args: (error: impl Display),
msg: format!("Failed to parse the `aleo new` command.\nSnarkVM Error: {error}"),
msg: format!("Failed to parse the `new` command.\nSnarkVM Error: {error}"),
help: None,
}

@backtraced
failed_to_parse_aleo_run {
failed_to_parse_run {
args: (error: impl Display),
msg: format!("Failed to parse the `aleo run` command.\nSnarkVM Error: {error}"),
msg: format!("Failed to parse the `run` command.\nSnarkVM Error: {error}"),
help: None,
}

@backtraced
failed_to_parse_aleo_node {
failed_to_parse_node {
args: (error: impl Display),
msg: format!("Failed to parse the `aleo node` command.\nSnarkVM Error: {error}"),
msg: format!("Failed to parse the `node` command.\nSnarkVM Error: {error}"),
help: None,
}

@backtraced
failed_to_parse_aleo_deploy {
failed_to_parse_deploy {
args: (error: impl Display),
msg: format!("Failed to parse the `aleo deploy` command.\nSnarkVM Error: {error}"),
msg: format!("Failed to parse the `deploy` command.\nSnarkVM Error: {error}"),
help: None,
}

@backtraced
failed_to_parse_execute {
args: (error: impl Display),
msg: format!("Failed to parse the `execute` command.\nSnarkVM Error: {error}"),
help: None,
}

@backtraced
failed_to_execute_execute {
args: (error: impl Display),
msg: format!("Failed to execute the `execute` command.\nSnarkVM Error: {error}"),
help: None,
}
);
8 changes: 8 additions & 0 deletions errors/src/errors/package/package_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,4 +305,12 @@ create_messages!(
msg: "The `src/` directory can contain only one file and must be named `main.leo`.".to_string(),
help: None,
}

/// For when the environment file has an IO error.
@backtraced
io_error_env_file {
args: (error: impl ErrorArg),
msg: format!("IO error env file from the provided file path - {error}"),
help: None,
}
);
17 changes: 9 additions & 8 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,17 @@ This directory includes the following Leo code examples:
6. Message -> Initialization of a struct
7. Token -> Record example

## Build Guide

To compile each example, run:
```bash
leo build
```
When you run this command for the first time the snarkvm parameters (universal setup) will be downloaded, these are necessary to run the programs.
## Run Guide

To run each program, run:
```bash
leo run main
```
This command will look in the input file inputs/*.in where should find a section [main] and use the variables as inputs to the program.
This command will look in the input file inputs/*.in where should find a section [main] and use the variables as inputs to the program.

## Execute Guide

To execute each program call, run:
```bash
leo execute main <inputs> --endpoint <endpoint>
```
4 changes: 4 additions & 0 deletions examples/auction/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

NETWORK=testnet3
PRIVATE_KEY=APrivateKey1zkp5wvamYgK3WCAdpBQxZqQX8XnuN2u11Y6QprZTriVwZVc

4 changes: 3 additions & 1 deletion examples/auction/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
outputs/
build/
*.avm
*.prover
*.verifier
11 changes: 4 additions & 7 deletions examples/auction/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,14 @@ Leo provides users with a command line interface for compiling and running Leo p
Users may either specify input values via the command line or provide an input file in `inputs/`.

### Configuring Accounts
The `program.json` file contains a private key and address.
The `.env` file contains a private key.
This is the account that will be used to sign transactions and is checked for record ownership.
When executing programs as different parties, be sure to set the `private_key` and `address` fields in `program.json` to the appropriate values.
When executing programs as different parties, be sure to set the `PRIVATE_KEY` field in `.env` to the appropriate values.
See `./run.sh` for an example of how to run the program as different parties.


The [Aleo SDK](https://github.com/AleoHQ/leo/tree/testnet3) provides a command line interface for generating new accounts.
To generate a new account, run
```
leo account new
```
The [Aleo SDK](https://github.com/AleoHQ/leo/tree/testnet3) provides an interface for generating new accounts.
To generate a new account, navigate to [aleo.tools](https://aleo.tools).


### Providing inputs via the command line.
Expand Down
35 changes: 35 additions & 0 deletions examples/auction/build/main.aleo
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
program auction.aleo;

record Bid:
owner as address.private;
bidder as address.private;
amount as u64.private;
is_winner as boolean.private;


function place_bid:
input r0 as address.private;
input r1 as u64.private;
assert.eq self.caller r0;
cast aleo1fxs9s0w97lmkwlcmgn0z3nuxufdee5yck9wqrs0umevp7qs0sg9q5xxxzh r0 r1 false into r2 as Bid.record;
output r2 as Bid.record;


function resolve:
input r0 as Bid.record;
input r1 as Bid.record;
assert.eq self.caller aleo1fxs9s0w97lmkwlcmgn0z3nuxufdee5yck9wqrs0umevp7qs0sg9q5xxxzh;
gte r0.amount r1.amount into r2;
ternary r2 r0.owner r1.owner into r3;
ternary r2 r0.bidder r1.bidder into r4;
ternary r2 r0.amount r1.amount into r5;
ternary r2 r0.is_winner r1.is_winner into r6;
cast r3 r4 r5 r6 into r7 as Bid.record;
output r7 as Bid.record;


function finish:
input r0 as Bid.record;
assert.eq self.caller aleo1fxs9s0w97lmkwlcmgn0z3nuxufdee5yck9wqrs0umevp7qs0sg9q5xxxzh;
cast r0.bidder r0.bidder r0.amount true into r1 as Bid.record;
output r1 as Bid.record;
6 changes: 6 additions & 0 deletions examples/auction/build/program.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"program": "auction.aleo",
"version": "0.0.0",
"description": "",
"license": "MIT"
}
2 changes: 1 addition & 1 deletion examples/auction/inputs/auction.in
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ second: Bid = Bid {
bidder: aleo1fxs9s0w97lmkwlcmgn0z3nuxufdee5yck9wqrs0umevp7qs0sg9q5xxxzh,
amount: 90u64,
is_winner: false,
_nonce: 1635474322959998727812727786860193861506102794050195384593971440884677453921group,
_nonce: 1511010328912449299156978046557700301564153667442988008615502964863620401388group,
};

[finish]
Expand Down
4 changes: 0 additions & 4 deletions examples/auction/program.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,5 @@
"program": "auction.aleo",
"version": "0.0.0",
"description": "",
"development": {
"private_key": "APrivateKey1zkp5wvamYgK3WCAdpBQxZqQX8XnuN2u11Y6QprZTriVwZVc",
"address": "aleo1fxs9s0w97lmkwlcmgn0z3nuxufdee5yck9wqrs0umevp7qs0sg9q5xxxzh"
},
"license": "MIT"
}
Loading

0 comments on commit d44457f

Please sign in to comment.