mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-09-11 05:45:30 +03:00
Merge branch 'mainnet' into update/from-testnet3
This commit is contained in:
commit
e4e228c419
@ -18,7 +18,7 @@ fi
|
|||||||
|
|
||||||
# Swap in the private key of Alice.
|
# Swap in the private key of Alice.
|
||||||
echo "
|
echo "
|
||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkp1w8PTxrRgGfAtfKUSq43iQyVbdQHfhGbiNPEg2LVSEXR
|
PRIVATE_KEY=APrivateKey1zkp1w8PTxrRgGfAtfKUSq43iQyVbdQHfhGbiNPEg2LVSEXR
|
||||||
" > .env
|
" > .env
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ leo run mint_public aleo13ssze66adjjkt795z9u5wpq8h6kn0y2657726h4h3e3wfnez4vqsm30
|
|||||||
|
|
||||||
# Swap in the private key of Bob.
|
# Swap in the private key of Bob.
|
||||||
echo "
|
echo "
|
||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkpFo72g7N9iFt3JzzeG8CqsS5doAiXyFvNCgk2oHvjRCzF
|
PRIVATE_KEY=APrivateKey1zkpFo72g7N9iFt3JzzeG8CqsS5doAiXyFvNCgk2oHvjRCzF
|
||||||
" > .env
|
" > .env
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ leo run mint_private aleo17vy26rpdhqx4598y5gp7nvaa9rk7tnvl6ufhvvf4calsrrqdaqyshd
|
|||||||
|
|
||||||
# Swap in the private key of Alice.
|
# Swap in the private key of Alice.
|
||||||
echo "
|
echo "
|
||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkp1w8PTxrRgGfAtfKUSq43iQyVbdQHfhGbiNPEg2LVSEXR
|
PRIVATE_KEY=APrivateKey1zkp1w8PTxrRgGfAtfKUSq43iQyVbdQHfhGbiNPEg2LVSEXR
|
||||||
" > .env
|
" > .env
|
||||||
|
|
||||||
@ -120,7 +120,7 @@ leo run transfer_public aleo17vy26rpdhqx4598y5gp7nvaa9rk7tnvl6ufhvvf4calsrrqdaqy
|
|||||||
|
|
||||||
# Swap in the private key of Bob.
|
# Swap in the private key of Bob.
|
||||||
echo "
|
echo "
|
||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkpFo72g7N9iFt3JzzeG8CqsS5doAiXyFvNCgk2oHvjRCzF
|
PRIVATE_KEY=APrivateKey1zkpFo72g7N9iFt3JzzeG8CqsS5doAiXyFvNCgk2oHvjRCzF
|
||||||
" > .env
|
" > .env
|
||||||
|
|
||||||
@ -158,7 +158,7 @@ leo run transfer_private "{
|
|||||||
|
|
||||||
# Swap in the private key of Alice.
|
# Swap in the private key of Alice.
|
||||||
echo "
|
echo "
|
||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkp1w8PTxrRgGfAtfKUSq43iQyVbdQHfhGbiNPEg2LVSEXR
|
PRIVATE_KEY=APrivateKey1zkp1w8PTxrRgGfAtfKUSq43iQyVbdQHfhGbiNPEg2LVSEXR
|
||||||
" > .env
|
" > .env
|
||||||
|
|
||||||
@ -193,7 +193,7 @@ leo run transfer_public_to_private aleo17vy26rpdhqx4598y5gp7nvaa9rk7tnvl6ufhvvf4
|
|||||||
|
|
||||||
# Swap in the private key of Bob.
|
# Swap in the private key of Bob.
|
||||||
echo "
|
echo "
|
||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkpFo72g7N9iFt3JzzeG8CqsS5doAiXyFvNCgk2oHvjRCzF
|
PRIVATE_KEY=APrivateKey1zkpFo72g7N9iFt3JzzeG8CqsS5doAiXyFvNCgk2oHvjRCzF
|
||||||
" > .env
|
" > .env
|
||||||
|
|
||||||
@ -234,6 +234,6 @@ leo run transfer_private_to_public "{
|
|||||||
# Swap in the private key of Alice.
|
# Swap in the private key of Alice.
|
||||||
# This is done to ensure that program.json is the same after every execution of ./run.sh.
|
# This is done to ensure that program.json is the same after every execution of ./run.sh.
|
||||||
echo "
|
echo "
|
||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkp1w8PTxrRgGfAtfKUSq43iQyVbdQHfhGbiNPEg2LVSEXR
|
PRIVATE_KEY=APrivateKey1zkp1w8PTxrRgGfAtfKUSq43iQyVbdQHfhGbiNPEg2LVSEXR
|
||||||
" > .env
|
" > .env
|
||||||
|
2
.github/dependabot.yml
vendored
2
.github/dependabot.yml
vendored
@ -5,7 +5,7 @@ updates:
|
|||||||
schedule:
|
schedule:
|
||||||
interval: daily
|
interval: daily
|
||||||
time: "10:00"
|
time: "10:00"
|
||||||
target-branch: "testnet3"
|
target-branch: "mainnet"
|
||||||
open-pull-requests-limit: 20
|
open-pull-requests-limit: 20
|
||||||
ignore:
|
ignore:
|
||||||
- dependency-name: snarkvm-curves
|
- dependency-name: snarkvm-curves
|
||||||
|
2
.github/workflows/acl2.yml
vendored
2
.github/workflows/acl2.yml
vendored
@ -21,7 +21,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Generate asts
|
- name: Generate asts
|
||||||
run: |
|
run: |
|
||||||
# This currently has to be on testnet3 to work:
|
# This currently has to be on mainnet to work:
|
||||||
cd compiler/parser
|
cd compiler/parser
|
||||||
cargo -q install --path . --example parser
|
cargo -q install --path . --example parser
|
||||||
# To ensure full file tests,
|
# To ensure full file tests,
|
||||||
|
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
@ -3,7 +3,7 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- testnet3
|
- mainnet
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- 'docs/**'
|
- 'docs/**'
|
||||||
- 'documentation/**'
|
- 'documentation/**'
|
||||||
@ -189,7 +189,7 @@ jobs:
|
|||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
ref: testnet3
|
ref: mainnet
|
||||||
|
|
||||||
- name: Install sccache
|
- name: Install sccache
|
||||||
env:
|
env:
|
||||||
|
2
.github/workflows/codecov.yml
vendored
2
.github/workflows/codecov.yml
vendored
@ -2,7 +2,7 @@ name: Code Coverage
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- testnet3
|
- mainnet
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- 'docs/**'
|
- 'docs/**'
|
||||||
- 'documentation/**'
|
- 'documentation/**'
|
||||||
|
2
.github/workflows/docs.yml
vendored
2
.github/workflows/docs.yml
vendored
@ -17,7 +17,7 @@ jobs:
|
|||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
ref: testnet3
|
ref: mainnet
|
||||||
|
|
||||||
- name: Install sccache
|
- name: Install sccache
|
||||||
env:
|
env:
|
||||||
|
@ -6,9 +6,9 @@ Thank you for your interest in contributing to Leo! Below you can find some guid
|
|||||||
|
|
||||||
Please follow the instructions below when filing pull requests:
|
Please follow the instructions below when filing pull requests:
|
||||||
|
|
||||||
- Ensure that your branch is forked from the current [testnet3](https://github.com/AleoHQ/leo/tree/testnet3) branch.
|
- Ensure that your branch is forked from the current [mainnet](https://github.com/AleoHQ/leo/tree/mainnet) branch.
|
||||||
- Fill out the provided markdown template for the feature or proposal. Be sure to link the pull request to any issues by using keywords. Example: "closes #130".
|
- Fill out the provided markdown template for the feature or proposal. Be sure to link the pull request to any issues by using keywords. Example: "closes #130".
|
||||||
- Run `cargo fmt` before you commit; we use the `nightly` version of `rustfmt` to format the code, so you'll need to have the `nightly` toolchain installed on your machine; there's a [git hook](https://git-scm.com/docs/githooks) that ensures proper formatting before any commits can be made, and [`.rustfmt.toml`](https://github.com/AleoHQ/Leo/blob/testnet3/.rustfmt.toml) specifies some of the formatting conventions.
|
- Run `cargo fmt` before you commit; we use the `nightly` version of `rustfmt` to format the code, so you'll need to have the `nightly` toolchain installed on your machine; there's a [git hook](https://git-scm.com/docs/githooks) that ensures proper formatting before any commits can be made, and [`.rustfmt.toml`](https://github.com/AleoHQ/Leo/blob/mainnet/.rustfmt.toml) specifies some of the formatting conventions.
|
||||||
- Run `cargo clippy` to ensure that popular correctness and performance pitfalls are avoided.
|
- Run `cargo clippy` to ensure that popular correctness and performance pitfalls are avoided.
|
||||||
|
|
||||||
## Style
|
## Style
|
||||||
|
7
Cargo.lock
generated
7
Cargo.lock
generated
@ -1966,6 +1966,7 @@ dependencies = [
|
|||||||
"toml 0.8.12",
|
"toml 0.8.12",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
|
"ureq",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
"zip 1.2.3",
|
"zip 1.2.3",
|
||||||
]
|
]
|
||||||
@ -2038,6 +2039,7 @@ dependencies = [
|
|||||||
"serde_json",
|
"serde_json",
|
||||||
"serial_test",
|
"serial_test",
|
||||||
"sha2",
|
"sha2",
|
||||||
|
"snarkvm",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"toml 0.8.12",
|
"toml 0.8.12",
|
||||||
"ureq",
|
"ureq",
|
||||||
@ -2068,6 +2070,7 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_yaml",
|
"serde_yaml",
|
||||||
|
"snarkvm",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -3147,9 +3150,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustversion"
|
name = "rustversion"
|
||||||
version = "1.0.16"
|
version = "1.0.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "092474d1a01ea8278f69e6a358998405fae5b8b963ddaeb2b0b04a128bf1dfb0"
|
checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rusty-hook"
|
name = "rusty-hook"
|
||||||
|
@ -64,6 +64,9 @@ default = [ ]
|
|||||||
ci_skip = [ "leo-compiler/ci_skip" ]
|
ci_skip = [ "leo-compiler/ci_skip" ]
|
||||||
noconfig = [ ]
|
noconfig = [ ]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
ureq = "2.9.7"
|
||||||
|
|
||||||
[dependencies.leo-ast]
|
[dependencies.leo-ast]
|
||||||
path = "./compiler/ast"
|
path = "./compiler/ast"
|
||||||
version = "=1.12.0"
|
version = "=1.12.0"
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://circleci.com/gh/AleoHQ/leo"><img src="https://circleci.com/gh/AleoHQ/leo.svg?style=svg&circle-token=00960191919c40be0774e00ce8f7fa1fcaa20c00"></a>
|
<a href="https://circleci.com/gh/AleoHQ/leo"><img src="https://circleci.com/gh/AleoHQ/leo.svg?style=svg&circle-token=00960191919c40be0774e00ce8f7fa1fcaa20c00"></a>
|
||||||
<a href="https://codecov.io/gh/AleoHQ/leo"><img src="https://codecov.io/gh/AleoHQ/leo/branch/testnet3/graph/badge.svg?token=S6MWO60SYL"/></a>
|
<a href="https://codecov.io/gh/AleoHQ/leo"><img src="https://codecov.io/gh/AleoHQ/leo/branch/mainnet/graph/badge.svg?token=S6MWO60SYL"/></a>
|
||||||
<a href="https://discord.gg/aleo"><img src="https://img.shields.io/discord/700454073459015690?logo=discord"/></a>
|
<a href="https://discord.gg/aleo"><img src="https://img.shields.io/discord/700454073459015690?logo=discord"/></a>
|
||||||
<a href="https://github.com/AleoHQ/leo/blob/testnet3/CONTRIBUTORS.md"><img src="https://img.shields.io/badge/contributors-393-ee8449"/></a>
|
<a href="https://github.com/AleoHQ/leo/blob/mainnet/CONTRIBUTORS.md"><img src="https://img.shields.io/badge/contributors-393-ee8449"/></a>
|
||||||
<a href="https://twitter.com/AleoHQ"><img src="https://img.shields.io/twitter/follow/AleoHQ?style=social"/></a>
|
<a href="https://twitter.com/AleoHQ"><img src="https://img.shields.io/twitter/follow/AleoHQ?style=social"/></a>
|
||||||
</p>
|
</p>
|
||||||
<div id="top"></div>
|
<div id="top"></div>
|
||||||
|
@ -41,6 +41,9 @@ version = "=1.12.0"
|
|||||||
[dependencies.sha2]
|
[dependencies.sha2]
|
||||||
version = "0.10"
|
version = "0.10"
|
||||||
|
|
||||||
|
[dependencies.snarkvm]
|
||||||
|
workspace = true
|
||||||
|
|
||||||
[dependencies.indexmap]
|
[dependencies.indexmap]
|
||||||
version = "1.9"
|
version = "1.9"
|
||||||
features = [ ]
|
features = [ ]
|
||||||
|
@ -17,6 +17,9 @@
|
|||||||
//! The compiler for Leo programs.
|
//! The compiler for Leo programs.
|
||||||
//!
|
//!
|
||||||
//! The [`Compiler`] type compiles Leo programs into R1CS circuits.
|
//! The [`Compiler`] type compiles Leo programs into R1CS circuits.
|
||||||
|
|
||||||
|
use crate::CompilerOptions;
|
||||||
|
|
||||||
pub use leo_ast::Ast;
|
pub use leo_ast::Ast;
|
||||||
use leo_ast::{NodeBuilder, Program, Stub};
|
use leo_ast::{NodeBuilder, Program, Stub};
|
||||||
use leo_errors::{emitter::Handler, CompilerError, Result};
|
use leo_errors::{emitter::Handler, CompilerError, Result};
|
||||||
@ -24,15 +27,15 @@ pub use leo_passes::SymbolTable;
|
|||||||
use leo_passes::*;
|
use leo_passes::*;
|
||||||
use leo_span::{source_map::FileName, symbol::with_session_globals, Symbol};
|
use leo_span::{source_map::FileName, symbol::with_session_globals, Symbol};
|
||||||
|
|
||||||
|
use snarkvm::prelude::Network;
|
||||||
|
|
||||||
|
use indexmap::{IndexMap, IndexSet};
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
use std::{fs, path::PathBuf};
|
use std::{fs, path::PathBuf};
|
||||||
|
|
||||||
use crate::CompilerOptions;
|
|
||||||
use indexmap::{IndexMap, IndexSet};
|
|
||||||
|
|
||||||
/// The primary entry point of the Leo compiler.
|
/// The primary entry point of the Leo compiler.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Compiler<'a> {
|
pub struct Compiler<'a, N: Network> {
|
||||||
/// The handler is used for error and warning emissions.
|
/// The handler is used for error and warning emissions.
|
||||||
handler: &'a Handler,
|
handler: &'a Handler,
|
||||||
/// The path to the main leo file.
|
/// The path to the main leo file.
|
||||||
@ -55,9 +58,11 @@ pub struct Compiler<'a> {
|
|||||||
type_table: TypeTable,
|
type_table: TypeTable,
|
||||||
/// The stubs for imported programs. Produced by `Retriever` module.
|
/// The stubs for imported programs. Produced by `Retriever` module.
|
||||||
import_stubs: IndexMap<Symbol, Stub>,
|
import_stubs: IndexMap<Symbol, Stub>,
|
||||||
|
// Allows the compiler to be generic over the network.
|
||||||
|
phantom: std::marker::PhantomData<N>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Compiler<'a> {
|
impl<'a, N: Network> Compiler<'a, N> {
|
||||||
/// Returns a new Leo compiler.
|
/// Returns a new Leo compiler.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
program_name: String,
|
program_name: String,
|
||||||
@ -83,6 +88,7 @@ impl<'a> Compiler<'a> {
|
|||||||
assigner,
|
assigner,
|
||||||
import_stubs,
|
import_stubs,
|
||||||
type_table,
|
type_table,
|
||||||
|
phantom: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,7 +112,7 @@ impl<'a> Compiler<'a> {
|
|||||||
let prg_sf = with_session_globals(|s| s.source_map.new_source(program_string, name));
|
let prg_sf = with_session_globals(|s| s.source_map.new_source(program_string, name));
|
||||||
|
|
||||||
// Use the parser to construct the abstract syntax tree (ast).
|
// Use the parser to construct the abstract syntax tree (ast).
|
||||||
self.ast = leo_parser::parse_ast(self.handler, &self.node_builder, &prg_sf.src, prg_sf.start_pos)?;
|
self.ast = leo_parser::parse_ast::<N>(self.handler, &self.node_builder, &prg_sf.src, prg_sf.start_pos)?;
|
||||||
|
|
||||||
// If the program is imported, then check that the name of its program scope matches the file name.
|
// If the program is imported, then check that the name of its program scope matches the file name.
|
||||||
// Note that parsing enforces that there is exactly one program scope in a file.
|
// Note that parsing enforces that there is exactly one program scope in a file.
|
||||||
@ -149,7 +155,7 @@ impl<'a> Compiler<'a> {
|
|||||||
|
|
||||||
/// Runs the type checker pass.
|
/// Runs the type checker pass.
|
||||||
pub fn type_checker_pass(&'a self, symbol_table: SymbolTable) -> Result<(SymbolTable, StructGraph, CallGraph)> {
|
pub fn type_checker_pass(&'a self, symbol_table: SymbolTable) -> Result<(SymbolTable, StructGraph, CallGraph)> {
|
||||||
let (symbol_table, struct_graph, call_graph) = TypeChecker::do_pass((
|
let (symbol_table, struct_graph, call_graph) = TypeChecker::<N>::do_pass((
|
||||||
&self.ast,
|
&self.ast,
|
||||||
self.handler,
|
self.handler,
|
||||||
symbol_table,
|
symbol_table,
|
||||||
|
@ -140,7 +140,8 @@ fn run_test(test: Test, handler: &Handler, buf: &BufferEmitter) -> Result<Value,
|
|||||||
handler.extend_if_error(process.add_program(&aleo_program).map_err(LeoError::Anyhow))?;
|
handler.extend_if_error(process.add_program(&aleo_program).map_err(LeoError::Anyhow))?;
|
||||||
|
|
||||||
// Add the bytecode to the import stubs.
|
// Add the bytecode to the import stubs.
|
||||||
let stub = handler.extend_if_error(disassemble_from_str(&bytecode).map_err(|err| err.into()))?;
|
let stub =
|
||||||
|
handler.extend_if_error(disassemble_from_str::<CurrentNetwork>(&bytecode).map_err(|err| err.into()))?;
|
||||||
import_stubs.insert(Symbol::intern(&program_name), stub);
|
import_stubs.insert(Symbol::intern(&program_name), stub);
|
||||||
|
|
||||||
// Hash the ast files.
|
// Hash the ast files.
|
||||||
|
@ -184,7 +184,8 @@ fn run_test(test: Test, handler: &Handler, buf: &BufferEmitter) -> Result<Value,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add the bytecode to the import stubs.
|
// Add the bytecode to the import stubs.
|
||||||
let stub = handler.extend_if_error(disassemble_from_str(&bytecode).map_err(|err| err.into()))?;
|
let stub =
|
||||||
|
handler.extend_if_error(disassemble_from_str::<CurrentNetwork>(&bytecode).map_err(|err| err.into()))?;
|
||||||
import_stubs.insert(Symbol::intern(&program_name), stub);
|
import_stubs.insert(Symbol::intern(&program_name), stub);
|
||||||
|
|
||||||
// Hash the ast files.
|
// Hash the ast files.
|
||||||
|
@ -156,7 +156,7 @@ pub fn new_compiler(
|
|||||||
main_file_path: PathBuf,
|
main_file_path: PathBuf,
|
||||||
compiler_options: Option<CompilerOptions>,
|
compiler_options: Option<CompilerOptions>,
|
||||||
import_stubs: IndexMap<Symbol, Stub>,
|
import_stubs: IndexMap<Symbol, Stub>,
|
||||||
) -> Compiler<'_> {
|
) -> Compiler<'_, CurrentNetwork> {
|
||||||
let output_dir = PathBuf::from("/tmp/output/");
|
let output_dir = PathBuf::from("/tmp/output/");
|
||||||
fs::create_dir_all(output_dir.clone()).unwrap();
|
fs::create_dir_all(output_dir.clone()).unwrap();
|
||||||
|
|
||||||
@ -178,7 +178,7 @@ pub fn parse_program<'a>(
|
|||||||
cwd: Option<PathBuf>,
|
cwd: Option<PathBuf>,
|
||||||
compiler_options: Option<CompilerOptions>,
|
compiler_options: Option<CompilerOptions>,
|
||||||
import_stubs: IndexMap<Symbol, Stub>,
|
import_stubs: IndexMap<Symbol, Stub>,
|
||||||
) -> Result<Compiler<'a>, LeoError> {
|
) -> Result<Compiler<'a, CurrentNetwork>, LeoError> {
|
||||||
let mut compiler = new_compiler(
|
let mut compiler = new_compiler(
|
||||||
program_name,
|
program_name,
|
||||||
handler,
|
handler,
|
||||||
@ -255,7 +255,7 @@ pub fn temp_dir() -> PathBuf {
|
|||||||
tempfile::tempdir().expect("Failed to open temporary directory").into_path()
|
tempfile::tempdir().expect("Failed to open temporary directory").into_path()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile_and_process<'a>(parsed: &'a mut Compiler<'a>) -> Result<String, LeoError> {
|
pub fn compile_and_process<'a>(parsed: &'a mut Compiler<'a, CurrentNetwork>) -> Result<String, LeoError> {
|
||||||
parsed.add_import_stubs()?;
|
parsed.add_import_stubs()?;
|
||||||
|
|
||||||
let st = parsed.symbol_table_pass()?;
|
let st = parsed.symbol_table_pass()?;
|
||||||
|
@ -26,6 +26,8 @@ use std::{
|
|||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type CurrentNetwork = snarkvm::prelude::MainnetV0;
|
||||||
|
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
#[clap(name = "leo parser", about = "Parse Leo AST and store it as a JSON")]
|
#[clap(name = "leo parser", about = "Parse Leo AST and store it as a JSON")]
|
||||||
struct Opt {
|
struct Opt {
|
||||||
@ -48,7 +50,7 @@ fn main() -> Result<(), String> {
|
|||||||
|
|
||||||
Handler::with(|h| {
|
Handler::with(|h| {
|
||||||
let node_builder = NodeBuilder::default();
|
let node_builder = NodeBuilder::default();
|
||||||
let ast = leo_parser::parse_ast(h, &node_builder, &code.src, code.start_pos)?;
|
let ast = leo_parser::parse_ast::<CurrentNetwork>(h, &node_builder, &code.src, code.start_pos)?;
|
||||||
let json = Ast::to_json_string(&ast)?;
|
let json = Ast::to_json_string(&ast)?;
|
||||||
println!("{json}");
|
println!("{json}");
|
||||||
Ok(json)
|
Ok(json)
|
||||||
|
@ -34,10 +34,17 @@ pub use parser::*;
|
|||||||
use leo_ast::{Ast, NodeBuilder};
|
use leo_ast::{Ast, NodeBuilder};
|
||||||
use leo_errors::{emitter::Handler, Result};
|
use leo_errors::{emitter::Handler, Result};
|
||||||
|
|
||||||
|
use snarkvm::prelude::Network;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test;
|
mod test;
|
||||||
|
|
||||||
/// Creates a new AST from a given file path and source code text.
|
/// Creates a new AST from a given file path and source code text.
|
||||||
pub fn parse_ast(handler: &Handler, node_builder: &NodeBuilder, source: &str, start_pos: BytePos) -> Result<Ast> {
|
pub fn parse_ast<N: Network>(
|
||||||
Ok(Ast::new(parser::parse(handler, node_builder, source, start_pos)?))
|
handler: &Handler,
|
||||||
|
node_builder: &NodeBuilder,
|
||||||
|
source: &str,
|
||||||
|
start_pos: BytePos,
|
||||||
|
) -> Result<Ast> {
|
||||||
|
Ok(Ast::new(parse::<N>(handler, node_builder, source, start_pos)?))
|
||||||
}
|
}
|
||||||
|
@ -20,11 +20,13 @@ use leo_ast::*;
|
|||||||
use leo_errors::{emitter::Handler, ParserError, ParserWarning, Result};
|
use leo_errors::{emitter::Handler, ParserError, ParserWarning, Result};
|
||||||
use leo_span::{Span, Symbol};
|
use leo_span::{Span, Symbol};
|
||||||
|
|
||||||
use std::{fmt::Display, mem};
|
use snarkvm::prelude::Network;
|
||||||
|
|
||||||
|
use std::{fmt::Display, marker::PhantomData, mem};
|
||||||
|
|
||||||
/// Stores a program in tokenized format plus additional context.
|
/// Stores a program in tokenized format plus additional context.
|
||||||
/// May be converted into a [`Program`] AST by parsing all tokens.
|
/// May be converted into a [`Program`] AST by parsing all tokens.
|
||||||
pub(crate) struct ParserContext<'a> {
|
pub(crate) struct ParserContext<'a, N: Network> {
|
||||||
/// Handler used to side-channel emit errors from the parser.
|
/// Handler used to side-channel emit errors from the parser.
|
||||||
pub(crate) handler: &'a Handler,
|
pub(crate) handler: &'a Handler,
|
||||||
/// Counter used to generate unique node ids.
|
/// Counter used to generate unique node ids.
|
||||||
@ -41,12 +43,14 @@ pub(crate) struct ParserContext<'a> {
|
|||||||
pub(crate) disallow_struct_construction: bool,
|
pub(crate) disallow_struct_construction: bool,
|
||||||
/// The name of the program being parsed.
|
/// The name of the program being parsed.
|
||||||
pub(crate) program_name: Option<Symbol>,
|
pub(crate) program_name: Option<Symbol>,
|
||||||
|
// Allows the parser to be generic over the network.
|
||||||
|
phantom: PhantomData<N>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Dummy span used to appease borrow checker.
|
/// Dummy span used to appease borrow checker.
|
||||||
const DUMMY_EOF: SpannedToken = SpannedToken { token: Token::Eof, span: Span::dummy() };
|
const DUMMY_EOF: SpannedToken = SpannedToken { token: Token::Eof, span: Span::dummy() };
|
||||||
|
|
||||||
impl<'a> ParserContext<'a> {
|
impl<'a, N: Network> ParserContext<'a, N> {
|
||||||
/// Returns a new [`ParserContext`] type given a vector of tokens.
|
/// Returns a new [`ParserContext`] type given a vector of tokens.
|
||||||
pub fn new(handler: &'a Handler, node_builder: &'a NodeBuilder, mut tokens: Vec<SpannedToken>) -> Self {
|
pub fn new(handler: &'a Handler, node_builder: &'a NodeBuilder, mut tokens: Vec<SpannedToken>) -> Self {
|
||||||
// Strip out comments.
|
// Strip out comments.
|
||||||
@ -63,6 +67,7 @@ impl<'a> ParserContext<'a> {
|
|||||||
token,
|
token,
|
||||||
tokens,
|
tokens,
|
||||||
program_name: None,
|
program_name: None,
|
||||||
|
phantom: Default::default(),
|
||||||
};
|
};
|
||||||
p.bump();
|
p.bump();
|
||||||
p
|
p
|
||||||
|
@ -18,7 +18,7 @@ use super::*;
|
|||||||
use leo_errors::{ParserError, Result};
|
use leo_errors::{ParserError, Result};
|
||||||
|
|
||||||
use leo_span::sym;
|
use leo_span::sym;
|
||||||
use snarkvm::console::{account::Address, network::MainnetV0};
|
use snarkvm::console::{account::Address, network::Network};
|
||||||
|
|
||||||
const INT_TYPES: &[Token] = &[
|
const INT_TYPES: &[Token] = &[
|
||||||
Token::I8,
|
Token::I8,
|
||||||
@ -36,7 +36,7 @@ const INT_TYPES: &[Token] = &[
|
|||||||
Token::Scalar,
|
Token::Scalar,
|
||||||
];
|
];
|
||||||
|
|
||||||
impl ParserContext<'_> {
|
impl<N: Network> ParserContext<'_, N> {
|
||||||
/// Returns an [`Expression`] AST node if the next token is an expression.
|
/// Returns an [`Expression`] AST node if the next token is an expression.
|
||||||
/// Includes struct init expressions.
|
/// Includes struct init expressions.
|
||||||
pub(crate) fn parse_expression(&mut self) -> Result<Expression> {
|
pub(crate) fn parse_expression(&mut self) -> Result<Expression> {
|
||||||
@ -769,7 +769,7 @@ impl ParserContext<'_> {
|
|||||||
Token::True => Expression::Literal(Literal::Boolean(true, span, self.node_builder.next_id())),
|
Token::True => Expression::Literal(Literal::Boolean(true, span, self.node_builder.next_id())),
|
||||||
Token::False => Expression::Literal(Literal::Boolean(false, span, self.node_builder.next_id())),
|
Token::False => Expression::Literal(Literal::Boolean(false, span, self.node_builder.next_id())),
|
||||||
Token::AddressLit(address_string) => {
|
Token::AddressLit(address_string) => {
|
||||||
if address_string.parse::<Address<MainnetV0>>().is_err() {
|
if address_string.parse::<Address<N>>().is_err() {
|
||||||
self.emit_err(ParserError::invalid_address_lit(&address_string, span));
|
self.emit_err(ParserError::invalid_address_lit(&address_string, span));
|
||||||
}
|
}
|
||||||
Expression::Literal(Literal::Address(address_string, span, self.node_builder.next_id()))
|
Expression::Literal(Literal::Address(address_string, span, self.node_builder.next_id()))
|
||||||
|
@ -18,7 +18,7 @@ use super::*;
|
|||||||
|
|
||||||
use leo_errors::{ParserError, Result};
|
use leo_errors::{ParserError, Result};
|
||||||
|
|
||||||
impl ParserContext<'_> {
|
impl<N: Network> ParserContext<'_, N> {
|
||||||
/// Returns a [`Program`] AST if all tokens can be consumed and represent a valid Leo program.
|
/// Returns a [`Program`] AST if all tokens can be consumed and represent a valid Leo program.
|
||||||
pub fn parse_program(&mut self) -> Result<Program> {
|
pub fn parse_program(&mut self) -> Result<Program> {
|
||||||
let mut imports = IndexMap::new();
|
let mut imports = IndexMap::new();
|
||||||
|
@ -23,10 +23,11 @@ use crate::{tokenizer::*, Token};
|
|||||||
|
|
||||||
use leo_ast::*;
|
use leo_ast::*;
|
||||||
use leo_errors::{emitter::Handler, Result};
|
use leo_errors::{emitter::Handler, Result};
|
||||||
use leo_span::Span;
|
use leo_span::{span::BytePos, Span};
|
||||||
|
|
||||||
|
use snarkvm::prelude::Network;
|
||||||
|
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use leo_span::span::BytePos;
|
|
||||||
use std::unreachable;
|
use std::unreachable;
|
||||||
|
|
||||||
mod context;
|
mod context;
|
||||||
@ -38,8 +39,13 @@ mod statement;
|
|||||||
pub(super) mod type_;
|
pub(super) mod type_;
|
||||||
|
|
||||||
/// Creates a new program from a given file path and source code text.
|
/// Creates a new program from a given file path and source code text.
|
||||||
pub fn parse(handler: &Handler, node_builder: &NodeBuilder, source: &str, start_pos: BytePos) -> Result<Program> {
|
pub fn parse<N: Network>(
|
||||||
let mut tokens = ParserContext::new(handler, node_builder, crate::tokenize(source, start_pos)?);
|
handler: &Handler,
|
||||||
|
node_builder: &NodeBuilder,
|
||||||
|
source: &str,
|
||||||
|
start_pos: BytePos,
|
||||||
|
) -> Result<Program> {
|
||||||
|
let mut tokens = ParserContext::<N>::new(handler, node_builder, crate::tokenize(source, start_pos)?);
|
||||||
|
|
||||||
tokens.parse_program()
|
tokens.parse_program()
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ const ASSIGN_TOKENS: &[Token] = &[
|
|||||||
Token::BitXorAssign,
|
Token::BitXorAssign,
|
||||||
];
|
];
|
||||||
|
|
||||||
impl ParserContext<'_> {
|
impl<N: Network> ParserContext<'_, N> {
|
||||||
/// Returns a [`Statement`] AST node if the next tokens represent a statement.
|
/// Returns a [`Statement`] AST node if the next tokens represent a statement.
|
||||||
pub(crate) fn parse_statement(&mut self) -> Result<Statement> {
|
pub(crate) fn parse_statement(&mut self) -> Result<Statement> {
|
||||||
match &self.token.token {
|
match &self.token.token {
|
||||||
|
@ -39,7 +39,7 @@ pub(super) const TYPE_TOKENS: &[Token] = &[
|
|||||||
Token::U128,
|
Token::U128,
|
||||||
];
|
];
|
||||||
|
|
||||||
impl ParserContext<'_> {
|
impl<N: Network> ParserContext<'_, N> {
|
||||||
/// Returns a [`IntegerType`] AST node if the given token is a supported integer type, or [`None`].
|
/// Returns a [`IntegerType`] AST node if the given token is a supported integer type, or [`None`].
|
||||||
pub(super) fn token_to_int_type(token: &Token) -> Option<IntegerType> {
|
pub(super) fn token_to_int_type(token: &Token) -> Option<IntegerType> {
|
||||||
Some(match token {
|
Some(match token {
|
||||||
|
@ -31,6 +31,8 @@ use serde::Serialize;
|
|||||||
use serde_yaml::Value;
|
use serde_yaml::Value;
|
||||||
use tokenizer::Token;
|
use tokenizer::Token;
|
||||||
|
|
||||||
|
type CurrentNetwork = snarkvm::prelude::MainnetV0;
|
||||||
|
|
||||||
// TODO: Enable parser warnings for passing tests
|
// TODO: Enable parser warnings for passing tests
|
||||||
|
|
||||||
struct TokenNamespace;
|
struct TokenNamespace;
|
||||||
@ -49,7 +51,7 @@ impl Namespace for TokenNamespace {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn not_fully_consumed(tokens: &mut ParserContext) -> Result<(), String> {
|
fn not_fully_consumed(tokens: &mut ParserContext<CurrentNetwork>) -> Result<(), String> {
|
||||||
if !tokens.has_next() {
|
if !tokens.has_next() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
@ -64,7 +66,7 @@ fn not_fully_consumed(tokens: &mut ParserContext) -> Result<(), String> {
|
|||||||
|
|
||||||
fn with_handler<T>(
|
fn with_handler<T>(
|
||||||
tokens: Vec<SpannedToken>,
|
tokens: Vec<SpannedToken>,
|
||||||
logic: impl FnOnce(&mut ParserContext<'_>) -> Result<T, LeoError>,
|
logic: impl FnOnce(&mut ParserContext<'_, CurrentNetwork>) -> Result<T, LeoError>,
|
||||||
) -> Result<T, String> {
|
) -> Result<T, String> {
|
||||||
let (handler, buf) = Handler::new_with_buf();
|
let (handler, buf) = Handler::new_with_buf();
|
||||||
let node_builder = NodeBuilder::default();
|
let node_builder = NodeBuilder::default();
|
||||||
|
@ -20,7 +20,7 @@ use leo_ast::*;
|
|||||||
use leo_errors::{emitter::Handler, TypeCheckerError};
|
use leo_errors::{emitter::Handler, TypeCheckerError};
|
||||||
use leo_span::{sym, Span, Symbol};
|
use leo_span::{sym, Span, Symbol};
|
||||||
|
|
||||||
use snarkvm::console::network::{MainnetV0, Network};
|
use snarkvm::console::network::Network;
|
||||||
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
@ -39,7 +39,7 @@ fn return_incorrect_type(t1: Option<Type>, t2: Option<Type>, expected: &Option<T
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
|
impl<'a, N: Network> ExpressionVisitor<'a> for TypeChecker<'a, N> {
|
||||||
type AdditionalInput = Option<Type>;
|
type AdditionalInput = Option<Type>;
|
||||||
type Output = Option<Type>;
|
type Output = Option<Type>;
|
||||||
|
|
||||||
@ -303,8 +303,9 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
|
|||||||
self.emit_err(TypeCheckerError::array_empty(input.span()));
|
self.emit_err(TypeCheckerError::array_empty(input.span()));
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
num_elements => {
|
||||||
|
if num_elements <= N::MAX_ARRAY_ELEMENTS {
|
||||||
// Check that the element types match.
|
// Check that the element types match.
|
||||||
1..=MainnetV0::MAX_ARRAY_ELEMENTS => {
|
|
||||||
let mut element_types = element_types.into_iter();
|
let mut element_types = element_types.into_iter();
|
||||||
// Note that this unwrap is safe because we already checked that the array is not empty.
|
// Note that this unwrap is safe because we already checked that the array is not empty.
|
||||||
element_types.next().unwrap().map(|first_type| {
|
element_types.next().unwrap().map(|first_type| {
|
||||||
@ -315,16 +316,12 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
|
|||||||
// Return the array type.
|
// Return the array type.
|
||||||
Type::Array(ArrayType::new(first_type, NonNegativeNumber::from(input.elements.len())))
|
Type::Array(ArrayType::new(first_type, NonNegativeNumber::from(input.elements.len())))
|
||||||
})
|
})
|
||||||
}
|
} else {
|
||||||
// The array cannot have more than `MAX_ARRAY_ELEMENTS` elements.
|
// The array cannot have more than `MAX_ARRAY_ELEMENTS` elements.
|
||||||
num_elements => {
|
self.emit_err(TypeCheckerError::array_too_large(num_elements, N::MAX_ARRAY_ELEMENTS, input.span()));
|
||||||
self.emit_err(TypeCheckerError::array_too_large(
|
|
||||||
num_elements,
|
|
||||||
MainnetV0::MAX_ARRAY_ELEMENTS,
|
|
||||||
input.span(),
|
|
||||||
));
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// If the expected type is known, then check that the array type is the same as the expected type.
|
// If the expected type is known, then check that the array type is the same as the expected type.
|
||||||
@ -1001,7 +998,7 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
|
|||||||
|
|
||||||
Some(Type::Tuple(expected_types.clone()))
|
Some(Type::Tuple(expected_types.clone()))
|
||||||
} else {
|
} else {
|
||||||
// Tuples must be explicitly typed in testnet3.
|
// Tuples must be explicitly typed.
|
||||||
self.emit_err(TypeCheckerError::invalid_tuple(input.span()));
|
self.emit_err(TypeCheckerError::invalid_tuple(input.span()));
|
||||||
|
|
||||||
None
|
None
|
||||||
|
@ -20,12 +20,13 @@ use leo_ast::{Type, *};
|
|||||||
use leo_errors::{TypeCheckerError, TypeCheckerWarning};
|
use leo_errors::{TypeCheckerError, TypeCheckerWarning};
|
||||||
use leo_span::sym;
|
use leo_span::sym;
|
||||||
|
|
||||||
use snarkvm::console::network::{MainnetV0, Network};
|
use snarkvm::console::network::Network;
|
||||||
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
// TODO: Cleanup logic for tuples.
|
// TODO: Cleanup logic for tuples.
|
||||||
|
|
||||||
impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
|
impl<'a, N: Network> ProgramVisitor<'a> for TypeChecker<'a, N> {
|
||||||
fn visit_program(&mut self, input: &'a Program) {
|
fn visit_program(&mut self, input: &'a Program) {
|
||||||
// Typecheck the program's stubs.
|
// Typecheck the program's stubs.
|
||||||
input.stubs.iter().for_each(|(symbol, stub)| {
|
input.stubs.iter().for_each(|(symbol, stub)| {
|
||||||
@ -45,82 +46,6 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
|
|||||||
input.program_scopes.values().for_each(|scope| self.visit_program_scope(scope));
|
input.program_scopes.values().for_each(|scope| self.visit_program_scope(scope));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_stub(&mut self, input: &'a Stub) {
|
|
||||||
// Set the current program name.
|
|
||||||
self.scope_state.program_name = Some(input.stub_id.name.name);
|
|
||||||
|
|
||||||
// Cannot have constant declarations in stubs.
|
|
||||||
if !input.consts.is_empty() {
|
|
||||||
self.emit_err(TypeCheckerError::stubs_cannot_have_const_declarations(input.consts.first().unwrap().1.span));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Typecheck the program's structs.
|
|
||||||
input.structs.iter().for_each(|(_, function)| self.visit_struct_stub(function));
|
|
||||||
|
|
||||||
// Typecheck the program's functions.
|
|
||||||
input.functions.iter().for_each(|(_, function)| self.visit_function_stub(function));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_function_stub(&mut self, input: &'a FunctionStub) {
|
|
||||||
// Must not be an inline function
|
|
||||||
if input.variant == Variant::Inline {
|
|
||||||
self.emit_err(TypeCheckerError::stub_functions_must_not_be_inlines(input.span));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lookup function metadata in the symbol table.
|
|
||||||
// Note that this unwrap is safe since function metadata is stored in a prior pass.
|
|
||||||
let function_index = self
|
|
||||||
.symbol_table
|
|
||||||
.borrow()
|
|
||||||
.lookup_fn_symbol(Location::new(self.scope_state.program_name, input.identifier.name))
|
|
||||||
.unwrap()
|
|
||||||
.id;
|
|
||||||
|
|
||||||
// Enter the function's scope.
|
|
||||||
self.enter_scope(function_index);
|
|
||||||
|
|
||||||
// Create a new child scope for the function's parameters and body.
|
|
||||||
let scope_index = self.create_child_scope();
|
|
||||||
|
|
||||||
// Create future stubs.
|
|
||||||
if input.variant == Variant::AsyncFunction {
|
|
||||||
let finalize_input_map = &mut self.async_function_input_types;
|
|
||||||
let resolved_inputs: Vec<Type> = input
|
|
||||||
.input
|
|
||||||
.iter()
|
|
||||||
.map(|input| {
|
|
||||||
match &input.type_ {
|
|
||||||
Type::Future(f) => {
|
|
||||||
// Since we traverse stubs in post-order, we can assume that the corresponding finalize stub has already been traversed.
|
|
||||||
Type::Future(FutureType::new(
|
|
||||||
finalize_input_map.get(&f.location.clone().unwrap()).unwrap().clone(),
|
|
||||||
f.location.clone(),
|
|
||||||
true,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
_ => input.clone().type_,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
finalize_input_map
|
|
||||||
.insert(Location::new(self.scope_state.program_name, input.identifier.name), resolved_inputs);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Query helper function to type check function parameters and outputs.
|
|
||||||
self.check_function_signature(&Function::from(input.clone()));
|
|
||||||
|
|
||||||
// Exit the scope for the function's parameters and body.
|
|
||||||
self.exit_scope(scope_index);
|
|
||||||
|
|
||||||
// Exit the function's scope.
|
|
||||||
self.exit_scope(function_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_struct_stub(&mut self, input: &'a Composite) {
|
|
||||||
self.visit_struct(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_program_scope(&mut self, input: &'a ProgramScope) {
|
fn visit_program_scope(&mut self, input: &'a ProgramScope) {
|
||||||
// Set the current program name.
|
// Set the current program name.
|
||||||
self.scope_state.program_name = Some(input.program_id.name.name);
|
self.scope_state.program_name = Some(input.program_id.name.name);
|
||||||
@ -144,9 +69,9 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check that the number of mappings does not exceed the maximum.
|
// Check that the number of mappings does not exceed the maximum.
|
||||||
if mapping_count > MainnetV0::MAX_MAPPINGS {
|
if mapping_count > N::MAX_MAPPINGS {
|
||||||
self.emit_err(TypeCheckerError::too_many_mappings(
|
self.emit_err(TypeCheckerError::too_many_mappings(
|
||||||
MainnetV0::MAX_MAPPINGS,
|
N::MAX_MAPPINGS,
|
||||||
input.program_id.name.span + input.program_id.network.span,
|
input.program_id.name.span + input.program_id.network.span,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -167,9 +92,9 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
|
|||||||
|
|
||||||
// TODO: Need similar checks for structs (all in separate PR)
|
// TODO: Need similar checks for structs (all in separate PR)
|
||||||
// Check that the number of transitions does not exceed the maximum.
|
// Check that the number of transitions does not exceed the maximum.
|
||||||
if transition_count > MainnetV0::MAX_FUNCTIONS {
|
if transition_count > N::MAX_FUNCTIONS {
|
||||||
self.emit_err(TypeCheckerError::too_many_transitions(
|
self.emit_err(TypeCheckerError::too_many_transitions(
|
||||||
MainnetV0::MAX_FUNCTIONS,
|
N::MAX_FUNCTIONS,
|
||||||
input.program_id.name.span + input.program_id.network.span,
|
input.program_id.name.span + input.program_id.network.span,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -180,6 +105,22 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_stub(&mut self, input: &'a Stub) {
|
||||||
|
// Set the current program name.
|
||||||
|
self.scope_state.program_name = Some(input.stub_id.name.name);
|
||||||
|
|
||||||
|
// Cannot have constant declarations in stubs.
|
||||||
|
if !input.consts.is_empty() {
|
||||||
|
self.emit_err(TypeCheckerError::stubs_cannot_have_const_declarations(input.consts.first().unwrap().1.span));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Typecheck the program's structs.
|
||||||
|
input.structs.iter().for_each(|(_, function)| self.visit_struct_stub(function));
|
||||||
|
|
||||||
|
// Typecheck the program's functions.
|
||||||
|
input.functions.iter().for_each(|(_, function)| self.visit_function_stub(function));
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_struct(&mut self, input: &'a Composite) {
|
fn visit_struct(&mut self, input: &'a Composite) {
|
||||||
// Check for conflicting struct/record member names.
|
// Check for conflicting struct/record member names.
|
||||||
let mut used = HashSet::new();
|
let mut used = HashSet::new();
|
||||||
@ -406,4 +347,64 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_function_stub(&mut self, input: &'a FunctionStub) {
|
||||||
|
// Must not be an inline function
|
||||||
|
if input.variant == Variant::Inline {
|
||||||
|
self.emit_err(TypeCheckerError::stub_functions_must_not_be_inlines(input.span));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lookup function metadata in the symbol table.
|
||||||
|
// Note that this unwrap is safe since function metadata is stored in a prior pass.
|
||||||
|
let function_index = self
|
||||||
|
.symbol_table
|
||||||
|
.borrow()
|
||||||
|
.lookup_fn_symbol(Location::new(self.scope_state.program_name, input.identifier.name))
|
||||||
|
.unwrap()
|
||||||
|
.id;
|
||||||
|
|
||||||
|
// Enter the function's scope.
|
||||||
|
self.enter_scope(function_index);
|
||||||
|
|
||||||
|
// Create a new child scope for the function's parameters and body.
|
||||||
|
let scope_index = self.create_child_scope();
|
||||||
|
|
||||||
|
// Create future stubs.
|
||||||
|
if input.variant == Variant::AsyncFunction {
|
||||||
|
let finalize_input_map = &mut self.async_function_input_types;
|
||||||
|
let resolved_inputs: Vec<Type> = input
|
||||||
|
.input
|
||||||
|
.iter()
|
||||||
|
.map(|input| {
|
||||||
|
match &input.type_ {
|
||||||
|
Type::Future(f) => {
|
||||||
|
// Since we traverse stubs in post-order, we can assume that the corresponding finalize stub has already been traversed.
|
||||||
|
Type::Future(FutureType::new(
|
||||||
|
finalize_input_map.get(&f.location.clone().unwrap()).unwrap().clone(),
|
||||||
|
f.location.clone(),
|
||||||
|
true,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
_ => input.clone().type_,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
finalize_input_map
|
||||||
|
.insert(Location::new(self.scope_state.program_name, input.identifier.name), resolved_inputs);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query helper function to type check function parameters and outputs.
|
||||||
|
self.check_function_signature(&Function::from(input.clone()));
|
||||||
|
|
||||||
|
// Exit the scope for the function's parameters and body.
|
||||||
|
self.exit_scope(scope_index);
|
||||||
|
|
||||||
|
// Exit the function's scope.
|
||||||
|
self.exit_scope(function_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_struct_stub(&mut self, input: &'a Composite) {
|
||||||
|
self.visit_struct(input);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,8 +14,8 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
use super::*;
|
||||||
use crate::{ConditionalTreeNode, TypeChecker, VariableSymbol, VariableType};
|
use crate::{ConditionalTreeNode, TypeChecker, VariableSymbol, VariableType};
|
||||||
use itertools::Itertools;
|
|
||||||
|
|
||||||
use leo_ast::{
|
use leo_ast::{
|
||||||
Type::{Future, Tuple},
|
Type::{Future, Tuple},
|
||||||
@ -23,7 +23,9 @@ use leo_ast::{
|
|||||||
};
|
};
|
||||||
use leo_errors::TypeCheckerError;
|
use leo_errors::TypeCheckerError;
|
||||||
|
|
||||||
impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
|
use itertools::Itertools;
|
||||||
|
|
||||||
|
impl<'a, N: Network> StatementVisitor<'a> for TypeChecker<'a, N> {
|
||||||
fn visit_statement(&mut self, input: &'a Statement) {
|
fn visit_statement(&mut self, input: &'a Statement) {
|
||||||
// No statements can follow a return statement.
|
// No statements can follow a return statement.
|
||||||
if self.scope_state.has_return {
|
if self.scope_state.has_return {
|
||||||
|
@ -24,32 +24,17 @@ use crate::{
|
|||||||
VariableType,
|
VariableType,
|
||||||
};
|
};
|
||||||
|
|
||||||
use leo_ast::{
|
use leo_ast::*;
|
||||||
Composite,
|
|
||||||
CompositeType,
|
|
||||||
CoreConstant,
|
|
||||||
CoreFunction,
|
|
||||||
Expression,
|
|
||||||
Function,
|
|
||||||
Identifier,
|
|
||||||
IntegerType,
|
|
||||||
Location,
|
|
||||||
MappingType,
|
|
||||||
Mode,
|
|
||||||
Node,
|
|
||||||
Type,
|
|
||||||
Variant,
|
|
||||||
};
|
|
||||||
use leo_errors::{emitter::Handler, TypeCheckerError, TypeCheckerWarning};
|
use leo_errors::{emitter::Handler, TypeCheckerError, TypeCheckerWarning};
|
||||||
use leo_span::{Span, Symbol};
|
use leo_span::{Span, Symbol};
|
||||||
|
|
||||||
use snarkvm::console::network::{MainnetV0, Network};
|
use snarkvm::console::network::Network;
|
||||||
|
|
||||||
use indexmap::{IndexMap, IndexSet};
|
use indexmap::{IndexMap, IndexSet};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use std::cell::RefCell;
|
use std::{cell::RefCell, marker::PhantomData};
|
||||||
|
|
||||||
pub struct TypeChecker<'a> {
|
pub struct TypeChecker<'a, N: Network> {
|
||||||
/// The symbol table for the program.
|
/// The symbol table for the program.
|
||||||
pub(crate) symbol_table: RefCell<SymbolTable>,
|
pub(crate) symbol_table: RefCell<SymbolTable>,
|
||||||
/// A mapping from node IDs to their types.
|
/// A mapping from node IDs to their types.
|
||||||
@ -68,6 +53,8 @@ pub struct TypeChecker<'a> {
|
|||||||
pub(crate) async_function_input_types: IndexMap<Location, Vec<Type>>,
|
pub(crate) async_function_input_types: IndexMap<Location, Vec<Type>>,
|
||||||
/// The set of used composites.
|
/// The set of used composites.
|
||||||
pub(crate) used_structs: IndexSet<Symbol>,
|
pub(crate) used_structs: IndexSet<Symbol>,
|
||||||
|
// Allows the type checker to be generic over the network.
|
||||||
|
phantom: PhantomData<N>,
|
||||||
}
|
}
|
||||||
|
|
||||||
const ADDRESS_TYPE: Type = Type::Address;
|
const ADDRESS_TYPE: Type = Type::Address;
|
||||||
@ -114,7 +101,7 @@ const UNSIGNED_INT_TYPES: [Type; 5] = [
|
|||||||
const MAGNITUDE_TYPES: [Type; 3] =
|
const MAGNITUDE_TYPES: [Type; 3] =
|
||||||
[Type::Integer(IntegerType::U8), Type::Integer(IntegerType::U16), Type::Integer(IntegerType::U32)];
|
[Type::Integer(IntegerType::U8), Type::Integer(IntegerType::U16), Type::Integer(IntegerType::U32)];
|
||||||
|
|
||||||
impl<'a> TypeChecker<'a> {
|
impl<'a, N: Network> TypeChecker<'a, N> {
|
||||||
/// Returns a new type checker given a symbol table and error handler.
|
/// Returns a new type checker given a symbol table and error handler.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
symbol_table: SymbolTable,
|
symbol_table: SymbolTable,
|
||||||
@ -137,6 +124,7 @@ impl<'a> TypeChecker<'a> {
|
|||||||
await_checker: AwaitChecker::new(max_depth, !disabled),
|
await_checker: AwaitChecker::new(max_depth, !disabled),
|
||||||
async_function_input_types: IndexMap::new(),
|
async_function_input_types: IndexMap::new(),
|
||||||
used_structs: IndexSet::new(),
|
used_structs: IndexSet::new(),
|
||||||
|
phantom: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1100,9 +1088,10 @@ impl<'a> TypeChecker<'a> {
|
|||||||
// Check that the array length is valid.
|
// Check that the array length is valid.
|
||||||
match array_type.length() {
|
match array_type.length() {
|
||||||
0 => self.emit_err(TypeCheckerError::array_empty(span)),
|
0 => self.emit_err(TypeCheckerError::array_empty(span)),
|
||||||
1..=MainnetV0::MAX_ARRAY_ELEMENTS => {}
|
|
||||||
length => {
|
length => {
|
||||||
self.emit_err(TypeCheckerError::array_too_large(length, MainnetV0::MAX_ARRAY_ELEMENTS, span))
|
if length > N::MAX_ARRAY_ELEMENTS {
|
||||||
|
self.emit_err(TypeCheckerError::array_too_large(length, N::MAX_ARRAY_ELEMENTS, span))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check that the array element type is valid.
|
// Check that the array element type is valid.
|
||||||
|
@ -14,14 +14,16 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
mod await_checker;
|
||||||
|
|
||||||
pub mod check_expressions;
|
pub mod check_expressions;
|
||||||
|
|
||||||
pub mod check_program;
|
pub mod check_program;
|
||||||
|
|
||||||
pub mod check_statements;
|
pub mod check_statements;
|
||||||
|
|
||||||
mod await_checker;
|
|
||||||
pub mod checker;
|
pub mod checker;
|
||||||
|
|
||||||
mod scope_state;
|
mod scope_state;
|
||||||
|
|
||||||
pub use checker::*;
|
pub use checker::*;
|
||||||
@ -31,12 +33,14 @@ use crate::{CallGraph, Pass, StructGraph, SymbolTable, TypeTable};
|
|||||||
use leo_ast::{Ast, ProgramVisitor};
|
use leo_ast::{Ast, ProgramVisitor};
|
||||||
use leo_errors::{emitter::Handler, Result};
|
use leo_errors::{emitter::Handler, Result};
|
||||||
|
|
||||||
impl<'a> Pass for TypeChecker<'a> {
|
use snarkvm::prelude::Network;
|
||||||
|
|
||||||
|
impl<'a, N: Network> Pass for TypeChecker<'a, N> {
|
||||||
type Input = (&'a Ast, &'a Handler, SymbolTable, &'a TypeTable, usize, bool);
|
type Input = (&'a Ast, &'a Handler, SymbolTable, &'a TypeTable, usize, bool);
|
||||||
type Output = Result<(SymbolTable, StructGraph, CallGraph)>;
|
type Output = Result<(SymbolTable, StructGraph, CallGraph)>;
|
||||||
|
|
||||||
fn do_pass((ast, handler, st, tt, max_depth, await_checking): Self::Input) -> Self::Output {
|
fn do_pass((ast, handler, st, tt, max_depth, await_checking): Self::Input) -> Self::Output {
|
||||||
let mut visitor = TypeChecker::new(st, tt, handler, max_depth, await_checking);
|
let mut visitor = TypeChecker::<N>::new(st, tt, handler, max_depth, await_checking);
|
||||||
visitor.visit_program(ast.as_repr());
|
visitor.visit_program(ast.as_repr());
|
||||||
handler.last_err().map_err(|e| *e)?;
|
handler.last_err().map_err(|e| *e)?;
|
||||||
|
|
||||||
|
@ -12,8 +12,8 @@ You will know that the download has failed if you see the following error messag
|
|||||||
```bash
|
```bash
|
||||||
ATTENTION - "genesis.prover.1c9bbe9" does not exist, downloading this file remotely and storing it locally. Please ensure "genesis.prover.1c9bbe9" is stored in "/Users/xxx/.aleo/resources/genesis.prover.1c9bbe9".
|
ATTENTION - "genesis.prover.1c9bbe9" does not exist, downloading this file remotely and storing it locally. Please ensure "genesis.prover.1c9bbe9" is stored in "/Users/xxx/.aleo/resources/genesis.prover.1c9bbe9".
|
||||||
|
|
||||||
snarkvm_parameters::testnet3 - Downloading parameters...
|
snarkvm_parameters::mainnet - Downloading parameters...
|
||||||
snarkvm_parameters::testnet3 - thread `main` panicked at 'Failed to load proving key: Crate("curl::error", "Error { description: \"Transferred a partial file\", code: 18, extra: Some(\"transfer closed with 92197356 bytes remaining to read\") }")', /Users/xxx/.cargo/git/checkouts/snarkvm-f1160780ffe17de8/ea14990/parameters/src/testnet3/symbol_table_creation:95:9
|
snarkvm_parameters::mainnet - thread `main` panicked at 'Failed to load proving key: Crate("curl::error", "Error { description: \"Transferred a partial file\", code: 18, extra: Some(\"transfer closed with 92197356 bytes remaining to read\") }")', /Users/xxx/.cargo/git/checkouts/snarkvm-f1160780ffe17de8/ea14990/parameters/src/mainnet/symbol_table_creation:95:9
|
||||||
stack backtrace:
|
stack backtrace:
|
||||||
0: backtrace::capture::Backtrace::new
|
0: backtrace::capture::Backtrace::new
|
||||||
1: leo::set_panic_hook::{{closure}}
|
1: leo::set_panic_hook::{{closure}}
|
||||||
|
@ -371,10 +371,17 @@ create_messages!(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@backtraced
|
@backtraced
|
||||||
missing_on_chain_program_name {
|
invalid_file_name_dependency {
|
||||||
args: (),
|
args: (name: impl Display),
|
||||||
msg: "The name of the program to execute on-chain is missing.".to_string(),
|
msg: format!("The dependency program name `{name}` is invalid."),
|
||||||
help: Some("Either set `--local` to execute the local program on chain, or set `--program <PROGRAM>`.".to_string()),
|
help: Some("Aleo program names must only contain lower case letters, numbers and underscores.".to_string()),
|
||||||
|
}
|
||||||
|
|
||||||
|
@backtraced
|
||||||
|
dependency_not_found {
|
||||||
|
args: (name: impl Display),
|
||||||
|
msg: format!("The dependency program `{name}` was not found among the manifest's dependencies."),
|
||||||
|
help: None,
|
||||||
}
|
}
|
||||||
|
|
||||||
@backtraced
|
@backtraced
|
||||||
@ -383,4 +390,11 @@ create_messages!(
|
|||||||
msg: format!("Conflicting program names given to execute on chain: `{first}` and `{second}`."),
|
msg: format!("Conflicting program names given to execute on chain: `{first}` and `{second}`."),
|
||||||
help: Some("Either set `--local` to execute the local program on chain, or set `--program <PROGRAM>`.".to_string()),
|
help: Some("Either set `--local` to execute the local program on chain, or set `--program <PROGRAM>`.".to_string()),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@backtraced
|
||||||
|
missing_on_chain_program_name {
|
||||||
|
args: (),
|
||||||
|
msg: "The name of the program to execute on-chain is missing.".to_string(),
|
||||||
|
help: Some("Either set `--local` to execute the local program on chain, or set `--program <PROGRAM>`.".to_string()),
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
@ -211,7 +211,7 @@ create_messages!(
|
|||||||
invalid_associated_access {
|
invalid_associated_access {
|
||||||
args: (name: impl Display),
|
args: (name: impl Display),
|
||||||
msg: format!("Invalid associated access call to struct {name}."),
|
msg: format!("Invalid associated access call to struct {name}."),
|
||||||
help: Some("Double colon `::` syntax is only supported for core functions in Leo for testnet3.".to_string()),
|
help: Some("Double colon `::` syntax is only supported for core functions in Leo for mainnet.".to_string()),
|
||||||
}
|
}
|
||||||
|
|
||||||
@formatted
|
@formatted
|
||||||
|
@ -114,7 +114,7 @@ create_messages!(
|
|||||||
missing_network_error {
|
missing_network_error {
|
||||||
args: (dependency: impl Display),
|
args: (dependency: impl Display),
|
||||||
msg: format!("Dependency {dependency} is missing a network specification"),
|
msg: format!("Dependency {dependency} is missing a network specification"),
|
||||||
help: Some("Add a network specification to the dependency in the `program.json` file. Example: `network: \"testnet3\"`".to_string()),
|
help: Some("Add a network specification to the dependency in the `program.json` file. Example: `network: \"mainnet\"`".to_string()),
|
||||||
}
|
}
|
||||||
|
|
||||||
@formatted
|
@formatted
|
||||||
@ -140,8 +140,8 @@ create_messages!(
|
|||||||
|
|
||||||
@formatted
|
@formatted
|
||||||
failed_to_retrieve_from_endpoint {
|
failed_to_retrieve_from_endpoint {
|
||||||
args: (endpoint: impl Display, error: impl ErrorArg),
|
args: (error: impl ErrorArg),
|
||||||
msg: format!("Failed to retrieve from endpoint `{endpoint}`. Error: {error}"),
|
msg: format!("{error}"),
|
||||||
help: None,
|
help: None,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,4 +151,46 @@ create_messages!(
|
|||||||
msg: format!("Compiled file at `{path}` does not exist, cannot compile parent."),
|
msg: format!("Compiled file at `{path}` does not exist, cannot compile parent."),
|
||||||
help: Some("If you were using the `--non-recursive` flag, remove it and try again.".to_string()),
|
help: Some("If you were using the `--non-recursive` flag, remove it and try again.".to_string()),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@backtraced
|
||||||
|
invalid_input_id_len {
|
||||||
|
args: (input: impl Display, expected_type: impl Display),
|
||||||
|
msg: format!("Invalid input: {input}."),
|
||||||
|
help: Some(format!("Type `{expected_type}` must contain exactly 61 lowercase characters or numbers.")),
|
||||||
|
}
|
||||||
|
|
||||||
|
@backtraced
|
||||||
|
invalid_input_id {
|
||||||
|
args: (input: impl Display, expected_type: impl Display, expected_preface: impl Display),
|
||||||
|
msg: format!("Invalid input: {input}."),
|
||||||
|
help: Some(format!("Type `{expected_type}` must start with \"{expected_preface}\".")),
|
||||||
|
}
|
||||||
|
|
||||||
|
@backtraced
|
||||||
|
invalid_numerical_input {
|
||||||
|
args: (input: impl Display),
|
||||||
|
msg: format!("Invalid numerical input: {input}."),
|
||||||
|
help: Some("Input must be a valid u32.".to_string()),
|
||||||
|
}
|
||||||
|
|
||||||
|
@backtraced
|
||||||
|
invalid_range {
|
||||||
|
args: (),
|
||||||
|
msg: "The range must be less than or equal to 50 blocks.".to_string(),
|
||||||
|
help: None,
|
||||||
|
}
|
||||||
|
|
||||||
|
@backtraced
|
||||||
|
invalid_height_or_hash {
|
||||||
|
args: (input: impl Display),
|
||||||
|
msg: format!("Invalid input: {input}."),
|
||||||
|
help: Some("Input must be a valid height or hash. Valid hashes are 61 characters long, composed of only numbers and lower case letters, and be prefaced with \"ab1\".".to_string()),
|
||||||
|
}
|
||||||
|
|
||||||
|
@backtraced
|
||||||
|
invalid_field {
|
||||||
|
args: (field: impl Display),
|
||||||
|
msg: format!("Invalid field: {field}."),
|
||||||
|
help: Some("Field element must be numerical string with optional \"field\" suffix.".to_string()),
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
|
|
||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkp5wvamYgK3WCAdpBQxZqQX8XnuN2u11Y6QprZTriVwZVc
|
PRIVATE_KEY=APrivateKey1zkp5wvamYgK3WCAdpBQxZqQX8XnuN2u11Y6QprZTriVwZVc
|
||||||
|
|
||||||
|
@ -44,8 +44,8 @@ When executing programs as different parties, be sure to set the `PRIVATE_KEY` f
|
|||||||
See `./run.sh` for an example of how to run the program as different parties.
|
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 an interface for generating new accounts.
|
The [Aleo SDK](https://github.com/AleoHQ/leo/tree/mainnet) provides an interface for generating new accounts.
|
||||||
To generate a new account, navigate to [aleo.tools](https://aleo.tools).
|
To generate a new account, navigate to [provable.tools](https://provable.tools).
|
||||||
|
|
||||||
|
|
||||||
### Providing inputs via the command line.
|
### Providing inputs via the command line.
|
||||||
|
@ -37,7 +37,7 @@ echo "
|
|||||||
"
|
"
|
||||||
# Swap in the private key and address of the first bidder to .env.
|
# Swap in the private key and address of the first bidder to .env.
|
||||||
echo "
|
echo "
|
||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkpG9Af9z5Ha4ejVyMCqVFXRKknSm8L1ELEwcc4htk9YhVK
|
PRIVATE_KEY=APrivateKey1zkpG9Af9z5Ha4ejVyMCqVFXRKknSm8L1ELEwcc4htk9YhVK
|
||||||
" > .env
|
" > .env
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ leo run place_bid aleo1yzlta2q5h8t0fqe0v6dyh9mtv4aggd53fgzr068jvplqhvqsnvzq7pj2k
|
|||||||
|
|
||||||
# Swap in the private key and address of the second bidder to .env.
|
# Swap in the private key and address of the second bidder to .env.
|
||||||
echo "
|
echo "
|
||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkpAFshdsj2EqQzXh5zHceDapFWVCwR6wMCJFfkLYRKupug
|
PRIVATE_KEY=APrivateKey1zkpAFshdsj2EqQzXh5zHceDapFWVCwR6wMCJFfkLYRKupug
|
||||||
" > .env
|
" > .env
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ leo run place_bid aleo1esqchvevwn7n5p84e735w4dtwt2hdtu4dpguwgwy94tsxm2p7qpqmlrta
|
|||||||
|
|
||||||
# Swap in the private key and address of the auctioneer to .env.
|
# Swap in the private key and address of the auctioneer to .env.
|
||||||
echo "
|
echo "
|
||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkp5wvamYgK3WCAdpBQxZqQX8XnuN2u11Y6QprZTriVwZVc
|
PRIVATE_KEY=APrivateKey1zkp5wvamYgK3WCAdpBQxZqQX8XnuN2u11Y6QprZTriVwZVc
|
||||||
" > .env
|
" > .env
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
|
|
||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkpHtqVWT6fSHgUMNxsuVf7eaR6id2cj7TieKY1Z8CP5rCD
|
PRIVATE_KEY=APrivateKey1zkpHtqVWT6fSHgUMNxsuVf7eaR6id2cj7TieKY1Z8CP5rCD
|
||||||
|
|
||||||
|
@ -45,8 +45,8 @@ When executing programs as different parties, be sure to set the `PRIVATE_KEY` f
|
|||||||
See `./run.sh` for an example of how to run the program as different parties.
|
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 an interface for generating new accounts.
|
The [Aleo SDK](https://github.com/AleoHQ/leo/tree/mainnet) provides an interface for generating new accounts.
|
||||||
To generate a new account, navigate to [aleo.tools](https://aleo.tools).
|
To generate a new account, navigate to [provable.tools](https://provable.tools).
|
||||||
|
|
||||||
### Providing inputs via the command line.
|
### Providing inputs via the command line.
|
||||||
```bash
|
```bash
|
||||||
|
@ -18,7 +18,7 @@ fi
|
|||||||
|
|
||||||
# Swap in the private key and address of the bank to .env.
|
# Swap in the private key and address of the bank to .env.
|
||||||
echo "
|
echo "
|
||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkpHtqVWT6fSHgUMNxsuVf7eaR6id2cj7TieKY1Z8CP5rCD
|
PRIVATE_KEY=APrivateKey1zkpHtqVWT6fSHgUMNxsuVf7eaR6id2cj7TieKY1Z8CP5rCD
|
||||||
" > .env
|
" > .env
|
||||||
|
|
||||||
@ -67,7 +67,7 @@ leo run issue aleo1zeklp6dd8e764spe74xez6f8w27dlua3w7hl4z2uln03re52egpsv46ngg 10
|
|||||||
|
|
||||||
# Swap in the private key and address of the user to .env.
|
# Swap in the private key and address of the user to .env.
|
||||||
echo "
|
echo "
|
||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkp75cpr5NNQpVWc5mfsD9Uf2wg6XvHknf82iwB636q3rtc
|
PRIVATE_KEY=APrivateKey1zkp75cpr5NNQpVWc5mfsD9Uf2wg6XvHknf82iwB636q3rtc
|
||||||
" > .env
|
" > .env
|
||||||
|
|
||||||
@ -161,7 +161,7 @@ echo "
|
|||||||
|
|
||||||
# Swap in the private key and address of the bank to .env.
|
# Swap in the private key and address of the bank to .env.
|
||||||
echo "
|
echo "
|
||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkpHtqVWT6fSHgUMNxsuVf7eaR6id2cj7TieKY1Z8CP5rCD
|
PRIVATE_KEY=APrivateKey1zkpHtqVWT6fSHgUMNxsuVf7eaR6id2cj7TieKY1Z8CP5rCD
|
||||||
" > .env
|
" > .env
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
|
|
||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkp86FNGdKxjgAdgQZ967bqBanjuHkAaoRe19RK24ZCGsHH
|
PRIVATE_KEY=APrivateKey1zkp86FNGdKxjgAdgQZ967bqBanjuHkAaoRe19RK24ZCGsHH
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ echo "
|
|||||||
"
|
"
|
||||||
|
|
||||||
echo "
|
echo "
|
||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkpGKaJY47BXb6knSqmT3JZnBUEGBDFAWz2nMVSsjwYpJmm
|
PRIVATE_KEY=APrivateKey1zkpGKaJY47BXb6knSqmT3JZnBUEGBDFAWz2nMVSsjwYpJmm
|
||||||
" > .env
|
" > .env
|
||||||
|
|
||||||
@ -67,7 +67,7 @@ echo "
|
|||||||
"
|
"
|
||||||
(
|
(
|
||||||
echo "
|
echo "
|
||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkp86FNGdKxjgAdgQZ967bqBanjuHkAaoRe19RK24ZCGsHH
|
PRIVATE_KEY=APrivateKey1zkp86FNGdKxjgAdgQZ967bqBanjuHkAaoRe19RK24ZCGsHH
|
||||||
" > .env
|
" > .env
|
||||||
|
|
||||||
@ -115,7 +115,7 @@ echo "
|
|||||||
"
|
"
|
||||||
(
|
(
|
||||||
echo "
|
echo "
|
||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkpGKaJY47BXb6knSqmT3JZnBUEGBDFAWz2nMVSsjwYpJmm
|
PRIVATE_KEY=APrivateKey1zkpGKaJY47BXb6knSqmT3JZnBUEGBDFAWz2nMVSsjwYpJmm
|
||||||
" > .env
|
" > .env
|
||||||
|
|
||||||
@ -151,7 +151,7 @@ echo "
|
|||||||
(
|
(
|
||||||
|
|
||||||
echo "
|
echo "
|
||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkp86FNGdKxjgAdgQZ967bqBanjuHkAaoRe19RK24ZCGsHH
|
PRIVATE_KEY=APrivateKey1zkp86FNGdKxjgAdgQZ967bqBanjuHkAaoRe19RK24ZCGsHH
|
||||||
" > .env
|
" > .env
|
||||||
|
|
||||||
@ -186,7 +186,7 @@ echo "
|
|||||||
"
|
"
|
||||||
(
|
(
|
||||||
echo "
|
echo "
|
||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkpGKaJY47BXb6knSqmT3JZnBUEGBDFAWz2nMVSsjwYpJmm
|
PRIVATE_KEY=APrivateKey1zkpGKaJY47BXb6knSqmT3JZnBUEGBDFAWz2nMVSsjwYpJmm
|
||||||
" > .env
|
" > .env
|
||||||
|
|
||||||
@ -222,7 +222,7 @@ echo "
|
|||||||
(
|
(
|
||||||
|
|
||||||
echo "
|
echo "
|
||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkp86FNGdKxjgAdgQZ967bqBanjuHkAaoRe19RK24ZCGsHH
|
PRIVATE_KEY=APrivateKey1zkp86FNGdKxjgAdgQZ967bqBanjuHkAaoRe19RK24ZCGsHH
|
||||||
" > .env
|
" > .env
|
||||||
|
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
@ -1,2 +1,2 @@
|
|||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
@ -1,2 +1,2 @@
|
|||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
@ -1,2 +1,2 @@
|
|||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
@ -1,2 +1,2 @@
|
|||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
@ -1,2 +1,2 @@
|
|||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
@ -1,2 +1,2 @@
|
|||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
@ -1,2 +1,2 @@
|
|||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
@ -1,2 +1,2 @@
|
|||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
@ -1,2 +1,2 @@
|
|||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
@ -1,2 +1,2 @@
|
|||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
@ -1,3 +1,3 @@
|
|||||||
|
|
||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
@ -1,2 +1,2 @@
|
|||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
@ -1,2 +1,2 @@
|
|||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
@ -1,2 +1,2 @@
|
|||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
@ -1,2 +1,2 @@
|
|||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
@ -1,2 +1,2 @@
|
|||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
@ -1,2 +1,2 @@
|
|||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
@ -1,4 +1,4 @@
|
|||||||
|
|
||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkp1w8PTxrRgGfAtfKUSq43iQyVbdQHfhGbiNPEg2LVSEXR
|
PRIVATE_KEY=APrivateKey1zkp1w8PTxrRgGfAtfKUSq43iQyVbdQHfhGbiNPEg2LVSEXR
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ fi
|
|||||||
|
|
||||||
# Swap in the private key of Alice.
|
# Swap in the private key of Alice.
|
||||||
echo "
|
echo "
|
||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkp1w8PTxrRgGfAtfKUSq43iQyVbdQHfhGbiNPEg2LVSEXR
|
PRIVATE_KEY=APrivateKey1zkp1w8PTxrRgGfAtfKUSq43iQyVbdQHfhGbiNPEg2LVSEXR
|
||||||
" > .env
|
" > .env
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ leo run mint_public aleo13ssze66adjjkt795z9u5wpq8h6kn0y2657726h4h3e3wfnez4vqsm30
|
|||||||
|
|
||||||
# Swap in the private key of Bob.
|
# Swap in the private key of Bob.
|
||||||
echo "
|
echo "
|
||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkpFo72g7N9iFt3JzzeG8CqsS5doAiXyFvNCgk2oHvjRCzF
|
PRIVATE_KEY=APrivateKey1zkpFo72g7N9iFt3JzzeG8CqsS5doAiXyFvNCgk2oHvjRCzF
|
||||||
" > .env
|
" > .env
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ leo run mint_private aleo17vy26rpdhqx4598y5gp7nvaa9rk7tnvl6ufhvvf4calsrrqdaqyshd
|
|||||||
|
|
||||||
# Swap in the private key of Alice.
|
# Swap in the private key of Alice.
|
||||||
echo "
|
echo "
|
||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkp1w8PTxrRgGfAtfKUSq43iQyVbdQHfhGbiNPEg2LVSEXR
|
PRIVATE_KEY=APrivateKey1zkp1w8PTxrRgGfAtfKUSq43iQyVbdQHfhGbiNPEg2LVSEXR
|
||||||
" > .env
|
" > .env
|
||||||
|
|
||||||
@ -120,7 +120,7 @@ leo run transfer_public aleo17vy26rpdhqx4598y5gp7nvaa9rk7tnvl6ufhvvf4calsrrqdaqy
|
|||||||
|
|
||||||
# Swap in the private key of Bob.
|
# Swap in the private key of Bob.
|
||||||
echo "
|
echo "
|
||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkpFo72g7N9iFt3JzzeG8CqsS5doAiXyFvNCgk2oHvjRCzF
|
PRIVATE_KEY=APrivateKey1zkpFo72g7N9iFt3JzzeG8CqsS5doAiXyFvNCgk2oHvjRCzF
|
||||||
" > .env
|
" > .env
|
||||||
|
|
||||||
@ -158,7 +158,7 @@ leo run transfer_private "{
|
|||||||
|
|
||||||
# Swap in the private key of Alice.
|
# Swap in the private key of Alice.
|
||||||
echo "
|
echo "
|
||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkp1w8PTxrRgGfAtfKUSq43iQyVbdQHfhGbiNPEg2LVSEXR
|
PRIVATE_KEY=APrivateKey1zkp1w8PTxrRgGfAtfKUSq43iQyVbdQHfhGbiNPEg2LVSEXR
|
||||||
" > .env
|
" > .env
|
||||||
|
|
||||||
@ -193,7 +193,7 @@ leo run transfer_public_to_private aleo17vy26rpdhqx4598y5gp7nvaa9rk7tnvl6ufhvvf4
|
|||||||
|
|
||||||
# Swap in the private key of Bob.
|
# Swap in the private key of Bob.
|
||||||
echo "
|
echo "
|
||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkpFo72g7N9iFt3JzzeG8CqsS5doAiXyFvNCgk2oHvjRCzF
|
PRIVATE_KEY=APrivateKey1zkpFo72g7N9iFt3JzzeG8CqsS5doAiXyFvNCgk2oHvjRCzF
|
||||||
" > .env
|
" > .env
|
||||||
|
|
||||||
@ -234,6 +234,6 @@ leo run transfer_private_to_public "{
|
|||||||
# Swap in the private key of Alice.
|
# Swap in the private key of Alice.
|
||||||
# This is done to ensure that program.json is the same after every execution of ./run.sh.
|
# This is done to ensure that program.json is the same after every execution of ./run.sh.
|
||||||
echo "
|
echo "
|
||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkp1w8PTxrRgGfAtfKUSq43iQyVbdQHfhGbiNPEg2LVSEXR
|
PRIVATE_KEY=APrivateKey1zkp1w8PTxrRgGfAtfKUSq43iQyVbdQHfhGbiNPEg2LVSEXR
|
||||||
" > .env
|
" > .env
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
@ -1,2 +1,2 @@
|
|||||||
NETWORK=testnet3
|
NETWORK=mainnet
|
||||||
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
PRIVATE_KEY=APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx
|
@ -32,10 +32,10 @@ pub struct CLI {
|
|||||||
#[clap(subcommand)]
|
#[clap(subcommand)]
|
||||||
command: Commands,
|
command: Commands,
|
||||||
|
|
||||||
#[clap(long, global = true, help = "Optional path to Leo program root folder")]
|
#[clap(long, global = true, help = "Path to Leo program root folder")]
|
||||||
path: Option<PathBuf>,
|
path: Option<PathBuf>,
|
||||||
|
|
||||||
#[clap(long, global = true, help = "Optional path to aleo program registry.")]
|
#[clap(long, global = true, help = "Path to aleo program registry")]
|
||||||
pub home: Option<PathBuf>,
|
pub home: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,11 +47,6 @@ enum Commands {
|
|||||||
#[clap(subcommand)]
|
#[clap(subcommand)]
|
||||||
command: Account,
|
command: Account,
|
||||||
},
|
},
|
||||||
#[clap(about = "Add a new on-chain or local dependency to the current package.")]
|
|
||||||
Add {
|
|
||||||
#[clap(flatten)]
|
|
||||||
command: Add,
|
|
||||||
},
|
|
||||||
#[clap(about = "Create a new Leo package in a new directory")]
|
#[clap(about = "Create a new Leo package in a new directory")]
|
||||||
New {
|
New {
|
||||||
#[clap(flatten)]
|
#[clap(flatten)]
|
||||||
@ -77,12 +72,26 @@ enum Commands {
|
|||||||
#[clap(flatten)]
|
#[clap(flatten)]
|
||||||
command: Deploy,
|
command: Deploy,
|
||||||
},
|
},
|
||||||
|
#[clap(about = "Query live data from the Aleo network")]
|
||||||
|
Query {
|
||||||
|
#[clap(flatten)]
|
||||||
|
command: Query,
|
||||||
|
},
|
||||||
#[clap(about = "Compile the current package as a program")]
|
#[clap(about = "Compile the current package as a program")]
|
||||||
Build {
|
Build {
|
||||||
#[clap(flatten)]
|
#[clap(flatten)]
|
||||||
command: Build,
|
command: Build,
|
||||||
},
|
},
|
||||||
|
#[clap(about = "Add a new on-chain or local dependency to the current package.")]
|
||||||
|
Add {
|
||||||
|
#[clap(flatten)]
|
||||||
|
command: Add,
|
||||||
|
},
|
||||||
|
#[clap(about = "Remove a dependency from the current package.")]
|
||||||
|
Remove {
|
||||||
|
#[clap(flatten)]
|
||||||
|
command: Remove,
|
||||||
|
},
|
||||||
#[clap(about = "Clean the output directory")]
|
#[clap(about = "Clean the output directory")]
|
||||||
Clean {
|
Clean {
|
||||||
#[clap(flatten)]
|
#[clap(flatten)]
|
||||||
@ -124,11 +133,13 @@ pub fn run_with_args(cli: CLI) -> Result<()> {
|
|||||||
Commands::Account { command } => command.try_execute(context),
|
Commands::Account { command } => command.try_execute(context),
|
||||||
Commands::New { command } => command.try_execute(context),
|
Commands::New { command } => command.try_execute(context),
|
||||||
Commands::Build { command } => command.try_execute(context),
|
Commands::Build { command } => command.try_execute(context),
|
||||||
|
Commands::Query { command } => command.try_execute(context),
|
||||||
Commands::Clean { command } => command.try_execute(context),
|
Commands::Clean { command } => command.try_execute(context),
|
||||||
Commands::Deploy { command } => command.try_execute(context),
|
Commands::Deploy { command } => command.try_execute(context),
|
||||||
Commands::Example { command } => command.try_execute(context),
|
Commands::Example { command } => command.try_execute(context),
|
||||||
Commands::Run { command } => command.try_execute(context),
|
Commands::Run { command } => command.try_execute(context),
|
||||||
Commands::Execute { command } => command.try_execute(context),
|
Commands::Execute { command } => command.try_execute(context),
|
||||||
|
Commands::Remove { command } => command.try_execute(context),
|
||||||
Commands::Update { command } => command.try_execute(context),
|
Commands::Update { command } => command.try_execute(context),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -174,7 +185,7 @@ mod tests {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// TODO: Clear tmp directory
|
// TODO: Clear tmp directory
|
||||||
// let registry = temp_dir.join(".aleo").join("registry").join("testnet3");
|
// let registry = temp_dir.join(".aleo").join("registry").join("mainnet");
|
||||||
// std::fs::remove_dir_all(registry).unwrap();
|
// std::fs::remove_dir_all(registry).unwrap();
|
||||||
// std::fs::remove_dir_all(project_directory).unwrap();
|
// std::fs::remove_dir_all(project_directory).unwrap();
|
||||||
}
|
}
|
||||||
@ -384,7 +395,8 @@ function external_nested_function:
|
|||||||
command: Add {
|
command: Add {
|
||||||
name: "nested_example_layer_0".to_string(),
|
name: "nested_example_layer_0".to_string(),
|
||||||
local: None,
|
local: None,
|
||||||
network: "testnet3".to_string(),
|
network: "mainnet".to_string(),
|
||||||
|
clear: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
path: Some(project_directory.clone()),
|
path: Some(project_directory.clone()),
|
||||||
@ -396,7 +408,7 @@ function external_nested_function:
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Add custom `.aleo` directory
|
// Add custom `.aleo` directory
|
||||||
let registry = temp_dir.join(".aleo").join("registry").join("testnet3");
|
let registry = temp_dir.join(".aleo").join("registry").join("mainnet");
|
||||||
std::fs::create_dir_all(®istry).unwrap();
|
std::fs::create_dir_all(®istry).unwrap();
|
||||||
std::fs::write(registry.join("nested_example_layer_0.aleo"), nested_example_layer_0).unwrap();
|
std::fs::write(registry.join("nested_example_layer_0.aleo"), nested_example_layer_0).unwrap();
|
||||||
std::fs::write(registry.join("nested_example_layer_1.aleo"), nested_example_layer_1).unwrap();
|
std::fs::write(registry.join("nested_example_layer_1.aleo"), nested_example_layer_1).unwrap();
|
||||||
@ -477,7 +489,8 @@ program child.aleo {
|
|||||||
command: Add {
|
command: Add {
|
||||||
name: "parent".to_string(),
|
name: "parent".to_string(),
|
||||||
local: Some(parent_directory.clone()),
|
local: Some(parent_directory.clone()),
|
||||||
network: "testnet3".to_string(),
|
network: "mainnet".to_string(),
|
||||||
|
clear: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
path: Some(grandparent_directory.clone()),
|
path: Some(grandparent_directory.clone()),
|
||||||
@ -491,7 +504,8 @@ program child.aleo {
|
|||||||
command: Add {
|
command: Add {
|
||||||
name: "child".to_string(),
|
name: "child".to_string(),
|
||||||
local: Some(child_directory.clone()),
|
local: Some(child_directory.clone()),
|
||||||
network: "testnet3".to_string(),
|
network: "mainnet".to_string(),
|
||||||
|
clear: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
path: Some(grandparent_directory.clone()),
|
path: Some(grandparent_directory.clone()),
|
||||||
@ -505,7 +519,8 @@ program child.aleo {
|
|||||||
command: Add {
|
command: Add {
|
||||||
name: "child".to_string(),
|
name: "child".to_string(),
|
||||||
local: Some(child_directory.clone()),
|
local: Some(child_directory.clone()),
|
||||||
network: "testnet3".to_string(),
|
network: "mainnet".to_string(),
|
||||||
|
clear: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
path: Some(parent_directory.clone()),
|
path: Some(parent_directory.clone()),
|
||||||
@ -628,7 +643,8 @@ program outer.aleo {
|
|||||||
command: Add {
|
command: Add {
|
||||||
name: "inner_1".to_string(),
|
name: "inner_1".to_string(),
|
||||||
local: Some(inner_1_directory.clone()),
|
local: Some(inner_1_directory.clone()),
|
||||||
network: "testnet3".to_string(),
|
network: "mainnet".to_string(),
|
||||||
|
clear: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
path: Some(outer_directory.clone()),
|
path: Some(outer_directory.clone()),
|
||||||
@ -642,7 +658,8 @@ program outer.aleo {
|
|||||||
command: Add {
|
command: Add {
|
||||||
name: "inner_2".to_string(),
|
name: "inner_2".to_string(),
|
||||||
local: Some(inner_2_directory.clone()),
|
local: Some(inner_2_directory.clone()),
|
||||||
network: "testnet3".to_string(),
|
network: "mainnet".to_string(),
|
||||||
|
clear: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
path: Some(outer_directory.clone()),
|
path: Some(outer_directory.clone()),
|
||||||
@ -795,7 +812,8 @@ program outer_2.aleo {
|
|||||||
command: Add {
|
command: Add {
|
||||||
name: "inner_1".to_string(),
|
name: "inner_1".to_string(),
|
||||||
local: Some(inner_1_directory.clone()),
|
local: Some(inner_1_directory.clone()),
|
||||||
network: "testnet3".to_string(),
|
network: "mainnet".to_string(),
|
||||||
|
clear: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
path: Some(outer_directory.clone()),
|
path: Some(outer_directory.clone()),
|
||||||
@ -809,7 +827,8 @@ program outer_2.aleo {
|
|||||||
command: Add {
|
command: Add {
|
||||||
name: "inner_2".to_string(),
|
name: "inner_2".to_string(),
|
||||||
local: Some(inner_2_directory.clone()),
|
local: Some(inner_2_directory.clone()),
|
||||||
network: "testnet3".to_string(),
|
network: "mainnet".to_string(),
|
||||||
|
clear: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
path: Some(outer_directory.clone()),
|
path: Some(outer_directory.clone()),
|
||||||
|
@ -214,7 +214,7 @@ fn print_keys(private_key: PrivateKey<CurrentNetwork>, discreet: bool) -> Result
|
|||||||
|
|
||||||
// Write the network and private key to the .env file in project directory.
|
// Write the network and private key to the .env file in project directory.
|
||||||
fn write_to_env_file(private_key: PrivateKey<CurrentNetwork>, ctx: &Context) -> Result<()> {
|
fn write_to_env_file(private_key: PrivateKey<CurrentNetwork>, ctx: &Context) -> Result<()> {
|
||||||
let data = format!("NETWORK=testnet3\nPRIVATE_KEY={private_key}\n");
|
let data = format!("NETWORK=mainnet\nPRIVATE_KEY={private_key}\n");
|
||||||
let program_dir = ctx.dir()?;
|
let program_dir = ctx.dir()?;
|
||||||
Env::<CurrentNetwork>::from(data).write_to(&program_dir)?;
|
Env::<CurrentNetwork>::from(data).write_to(&program_dir)?;
|
||||||
tracing::info!("✅ Private Key written to {}", program_dir.join(".env").display());
|
tracing::info!("✅ Private Key written to {}", program_dir.join(".env").display());
|
||||||
|
@ -15,21 +15,24 @@
|
|||||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use leo_retriever::{Dependency, Location, Manifest, Network};
|
use leo_retriever::{Dependency, Location, Manifest, NetworkName};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
/// Clean outputs folder command
|
/// Add a new on-chain or local dependency to the current package.
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[clap(name = "leo", author = "The Aleo Team <hello@aleo.org>", version)]
|
#[clap(name = "leo", author = "The Aleo Team <hello@aleo.org>", version)]
|
||||||
pub struct Add {
|
pub struct Add {
|
||||||
#[clap(name = "NAME", help = "The dependency name")]
|
#[clap(name = "NAME", help = "The dependency name. Ex: `credits.aleo` or `credits`.")]
|
||||||
pub(crate) name: String,
|
pub(crate) name: String,
|
||||||
|
|
||||||
#[clap(short = 'l', long, help = "Optional path to local dependency")]
|
#[clap(short = 'l', long, help = "Path to local dependency")]
|
||||||
pub(crate) local: Option<PathBuf>,
|
pub(crate) local: Option<PathBuf>,
|
||||||
|
|
||||||
#[clap(short = 'n', long, help = "Optional name of the network to use", default_value = "testnet3")]
|
#[clap(short = 'n', long, help = "Name of the network to use", default_value = "mainnet")]
|
||||||
pub(crate) network: String,
|
pub(crate) network: String,
|
||||||
|
|
||||||
|
#[clap(short = 'c', long, help = "Clear all previous dependencies.", default_value = "false")]
|
||||||
|
pub(crate) clear: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Command for Add {
|
impl Command for Add {
|
||||||
@ -47,41 +50,74 @@ impl Command for Add {
|
|||||||
fn apply(self, context: Context, _: Self::Input) -> Result<Self::Output> {
|
fn apply(self, context: Context, _: Self::Input) -> Result<Self::Output> {
|
||||||
let path = context.dir()?;
|
let path = context.dir()?;
|
||||||
|
|
||||||
// Deserialize the manifest
|
// Deserialize the manifest.
|
||||||
let program_data: String = std::fs::read_to_string(path.join("program.json"))
|
let program_data: String = std::fs::read_to_string(path.join("program.json"))
|
||||||
.map_err(|err| PackageError::failed_to_read_file(path.to_str().unwrap(), err))?;
|
.map_err(|err| PackageError::failed_to_read_file(path.to_str().unwrap(), err))?;
|
||||||
let manifest: Manifest = serde_json::from_str(&program_data)
|
let manifest: Manifest = serde_json::from_str(&program_data)
|
||||||
.map_err(|err| PackageError::failed_to_deserialize_manifest_file(path.to_str().unwrap(), err))?;
|
.map_err(|err| PackageError::failed_to_deserialize_manifest_file(path.to_str().unwrap(), err))?;
|
||||||
|
|
||||||
// Allow both `credits.aleo` and `credits` syntax
|
// Make sure the program name is valid.
|
||||||
let name = match self.name {
|
// Allow both `credits.aleo` and `credits` syntax.
|
||||||
name if name.ends_with(".aleo") => name,
|
let name: String = match &self.name {
|
||||||
name => format!("{}.aleo", name),
|
name if name.ends_with(".aleo")
|
||||||
|
&& Package::<CurrentNetwork>::is_aleo_name_valid(&name[0..self.name.len() - 5]) =>
|
||||||
|
{
|
||||||
|
name.clone()
|
||||||
|
}
|
||||||
|
name if Package::<CurrentNetwork>::is_aleo_name_valid(name) => format!("{name}.aleo"),
|
||||||
|
name => return Err(PackageError::invalid_file_name_dependency(name).into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add dependency section to manifest if it doesn't exist
|
// Add dependency section to manifest if it doesn't exist.
|
||||||
let mut dependencies = match manifest.dependencies() {
|
let mut dependencies = match (self.clear, manifest.dependencies()) {
|
||||||
Some(ref dependencies) => dependencies
|
(false, Some(ref dependencies)) => dependencies
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|dependency| {
|
.filter_map(|dependency| {
|
||||||
|
// Overwrite old dependencies of the same name.
|
||||||
if dependency.name() == &name {
|
if dependency.name() == &name {
|
||||||
println!("{} already exists as a dependency. Overwriting.", name);
|
let msg = match (dependency.path(), dependency.network()) {
|
||||||
|
(Some(local_path), _) => {
|
||||||
|
format!("local dependency at path `{}`", local_path.to_str().unwrap().replace('\"', ""))
|
||||||
|
}
|
||||||
|
(_, Some(network)) => {
|
||||||
|
format!("network dependency from `{}`", network)
|
||||||
|
}
|
||||||
|
_ => "git dependency".to_string(),
|
||||||
|
};
|
||||||
|
tracing::warn!("⚠️ Program `{name}` already exists as a {msg}. Overwriting.");
|
||||||
|
None
|
||||||
|
} else if self.local.is_some() && &self.local == dependency.path() {
|
||||||
|
// Overwrite old dependencies at the same local path.
|
||||||
|
tracing::warn!(
|
||||||
|
"⚠️ Path `{}` already exists as the location for local dependency `{}`. Overwriting.",
|
||||||
|
self.local.clone().unwrap().to_str().unwrap().replace('\"', ""),
|
||||||
|
dependency.name()
|
||||||
|
);
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(dependency.clone())
|
Some(dependency.clone())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
None => Vec::new(),
|
_ => Vec::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add new dependency to manifest
|
// Add new dependency to the manifest.
|
||||||
dependencies.push(match self.local {
|
dependencies.push(match self.local {
|
||||||
Some(local_path) => Dependency::new(name, Location::Local, None, Some(local_path)),
|
Some(local_path) => {
|
||||||
None => Dependency::new(name, Location::Network, Some(Network::from(&self.network)), None),
|
tracing::info!(
|
||||||
|
"✅ Added local dependency to program `{name}` at path `{}`.",
|
||||||
|
local_path.to_str().unwrap().replace('\"', "")
|
||||||
|
);
|
||||||
|
Dependency::new(name, Location::Local, None, Some(local_path))
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
tracing::info!("✅ Added network dependency to program `{name}` from network `{}`.", self.network);
|
||||||
|
Dependency::new(name, Location::Network, Some(NetworkName::from(&self.network)), None)
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Update manifest
|
// Update the manifest file.
|
||||||
let new_manifest = Manifest::new(
|
let new_manifest = Manifest::new(
|
||||||
manifest.program(),
|
manifest.program(),
|
||||||
manifest.version(),
|
manifest.version(),
|
||||||
|
@ -23,10 +23,7 @@ use leo_package::{build::BuildDirectory, outputs::OutputsDirectory, source::Sour
|
|||||||
use leo_retriever::Retriever;
|
use leo_retriever::Retriever;
|
||||||
use leo_span::Symbol;
|
use leo_span::Symbol;
|
||||||
|
|
||||||
use snarkvm::{
|
use snarkvm::{package::Package, prelude::ProgramID};
|
||||||
package::Package,
|
|
||||||
prelude::{MainnetV0, ProgramID},
|
|
||||||
};
|
|
||||||
|
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use std::{
|
use std::{
|
||||||
@ -34,8 +31,6 @@ use std::{
|
|||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
|
|
||||||
type CurrentNetwork = MainnetV0;
|
|
||||||
|
|
||||||
impl From<BuildOptions> for CompilerOptions {
|
impl From<BuildOptions> for CompilerOptions {
|
||||||
fn from(options: BuildOptions) -> Self {
|
fn from(options: BuildOptions) -> Self {
|
||||||
let mut out_options = Self {
|
let mut out_options = Self {
|
||||||
@ -109,7 +104,8 @@ impl Command for Build {
|
|||||||
|
|
||||||
// Retrieve all local dependencies in post order
|
// Retrieve all local dependencies in post order
|
||||||
let main_sym = Symbol::intern(&program_id.name().to_string());
|
let main_sym = Symbol::intern(&program_id.name().to_string());
|
||||||
let mut retriever = Retriever::new(main_sym, &package_path, &home_path, self.options.endpoint.clone())
|
let mut retriever =
|
||||||
|
Retriever::<CurrentNetwork>::new(main_sym, &package_path, &home_path, self.options.endpoint.clone())
|
||||||
.map_err(|err| UtilError::failed_to_retrieve_dependencies(err, Default::default()))?;
|
.map_err(|err| UtilError::failed_to_retrieve_dependencies(err, Default::default()))?;
|
||||||
let mut local_dependencies =
|
let mut local_dependencies =
|
||||||
retriever.retrieve().map_err(|err| UtilError::failed_to_retrieve_dependencies(err, Default::default()))?;
|
retriever.retrieve().map_err(|err| UtilError::failed_to_retrieve_dependencies(err, Default::default()))?;
|
||||||
@ -142,7 +138,7 @@ impl Command for Build {
|
|||||||
for file_path in local_source_files {
|
for file_path in local_source_files {
|
||||||
compile_leo_file(
|
compile_leo_file(
|
||||||
file_path,
|
file_path,
|
||||||
&ProgramID::<MainnetV0>::try_from(format!("{}.aleo", dependency))
|
&ProgramID::<CurrentNetwork>::try_from(format!("{}.aleo", dependency))
|
||||||
.map_err(|_| UtilError::snarkvm_error_building_program_id(Default::default()))?,
|
.map_err(|_| UtilError::snarkvm_error_building_program_id(Default::default()))?,
|
||||||
&local_outputs_directory,
|
&local_outputs_directory,
|
||||||
&local_build_directory,
|
&local_build_directory,
|
||||||
@ -186,17 +182,13 @@ impl Command for Build {
|
|||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn compile_leo_file(
|
fn compile_leo_file(
|
||||||
file_path: PathBuf,
|
file_path: PathBuf,
|
||||||
program_id: &ProgramID<MainnetV0>,
|
program_id: &ProgramID<CurrentNetwork>,
|
||||||
outputs: &Path,
|
outputs: &Path,
|
||||||
build: &Path,
|
build: &Path,
|
||||||
handler: &Handler,
|
handler: &Handler,
|
||||||
options: BuildOptions,
|
options: BuildOptions,
|
||||||
stubs: IndexMap<Symbol, Stub>,
|
stubs: IndexMap<Symbol, Stub>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
// Construct the Leo file name with extension `foo.leo`.
|
|
||||||
let file_name =
|
|
||||||
file_path.file_name().and_then(|name| name.to_str()).ok_or_else(PackageError::failed_to_get_file_name)?;
|
|
||||||
|
|
||||||
// Construct program name from the program_id found in `package.json`.
|
// Construct program name from the program_id found in `package.json`.
|
||||||
let program_name = program_id.name().to_string();
|
let program_name = program_id.name().to_string();
|
||||||
|
|
||||||
@ -205,8 +197,8 @@ fn compile_leo_file(
|
|||||||
aleo_file_path.push(format!("main.{}", program_id.network()));
|
aleo_file_path.push(format!("main.{}", program_id.network()));
|
||||||
|
|
||||||
// Create a new instance of the Leo compiler.
|
// Create a new instance of the Leo compiler.
|
||||||
let mut compiler = Compiler::new(
|
let mut compiler = Compiler::<CurrentNetwork>::new(
|
||||||
program_name,
|
program_name.clone(),
|
||||||
program_id.network().to_string(),
|
program_id.network().to_string(),
|
||||||
handler,
|
handler,
|
||||||
file_path.clone(),
|
file_path.clone(),
|
||||||
@ -224,6 +216,6 @@ fn compile_leo_file(
|
|||||||
.write_all(instructions.as_bytes())
|
.write_all(instructions.as_bytes())
|
||||||
.map_err(CliError::failed_to_load_instructions)?;
|
.map_err(CliError::failed_to_load_instructions)?;
|
||||||
|
|
||||||
tracing::info!("✅ Compiled '{}' into Aleo instructions", file_name);
|
tracing::info!("✅ Compiled '{program_name}.aleo' into Aleo instructions");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -35,12 +35,18 @@ pub use example::Example;
|
|||||||
pub mod execute;
|
pub mod execute;
|
||||||
pub use execute::Execute;
|
pub use execute::Execute;
|
||||||
|
|
||||||
|
pub mod query;
|
||||||
|
pub use query::Query;
|
||||||
|
|
||||||
pub mod new;
|
pub mod new;
|
||||||
pub use new::New;
|
pub use new::New;
|
||||||
|
|
||||||
// pub mod node;
|
// pub mod node;
|
||||||
// pub use node::Node;
|
// pub use node::Node;
|
||||||
|
|
||||||
|
pub mod remove;
|
||||||
|
pub use remove::Remove;
|
||||||
|
|
||||||
pub mod run;
|
pub mod run;
|
||||||
pub use run::Run;
|
pub use run::Run;
|
||||||
|
|
||||||
@ -168,7 +174,7 @@ pub struct BuildOptions {
|
|||||||
pub struct FeeOptions {
|
pub struct FeeOptions {
|
||||||
#[clap(long, help = "Priority fee in microcredits. Defaults to 0.", default_value = "0")]
|
#[clap(long, help = "Priority fee in microcredits. Defaults to 0.", default_value = "0")]
|
||||||
pub(crate) priority_fee: String,
|
pub(crate) priority_fee: String,
|
||||||
#[clap(long, help = "Network to broadcast to. Defaults to testnet3.", default_value = "testnet3")]
|
#[clap(long, help = "Network to broadcast to. Defaults to mainnet.", default_value = "mainnet")]
|
||||||
pub(crate) network: String,
|
pub(crate) network: String,
|
||||||
#[clap(long, help = "Private key to authorize fee expenditure.")]
|
#[clap(long, help = "Private key to authorize fee expenditure.")]
|
||||||
pub(crate) private_key: Option<String>,
|
pub(crate) private_key: Option<String>,
|
||||||
|
93
leo/cli/commands/query/block.rs
Normal file
93
leo/cli/commands/query/block.rs
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
// Copyright (C) 2019-2023 Aleo Systems Inc.
|
||||||
|
// This file is part of the Leo library.
|
||||||
|
|
||||||
|
// The Leo library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// The Leo library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
use crate::cli::context::Context;
|
||||||
|
use clap::Parser;
|
||||||
|
|
||||||
|
// Query on-chain information related to blocks.
|
||||||
|
#[derive(Parser, Debug)]
|
||||||
|
pub struct Block {
|
||||||
|
#[clap(help = "Fetch a block by specifying its height or hash", required_unless_present_any = &["latest", "latest_hash", "latest_height", "range"])]
|
||||||
|
pub(crate) id: Option<String>,
|
||||||
|
#[arg(short, long, help = "Get the latest block", default_value = "false", conflicts_with_all(["latest_hash", "latest_height", "range", "transactions", "to_height"]))]
|
||||||
|
pub(crate) latest: bool,
|
||||||
|
#[arg(short, long, help = "Get the latest block hash", default_value = "false", conflicts_with_all(["latest", "latest_height", "range", "transactions", "to_height"]))]
|
||||||
|
pub(crate) latest_hash: bool,
|
||||||
|
#[arg(short, long, help = "Get the latest block height", default_value = "false", conflicts_with_all(["latest", "latest_hash", "range", "transactions", "to_height"]))]
|
||||||
|
pub(crate) latest_height: bool,
|
||||||
|
#[arg(short, long, help = "Get up to 50 consecutive blocks", number_of_values = 2, value_names = &["START_HEIGHT", "END_HEIGHT"], conflicts_with_all(["latest", "latest_hash", "latest_height", "transactions", "to_height"]))]
|
||||||
|
pub(crate) range: Option<Vec<String>>,
|
||||||
|
#[arg(
|
||||||
|
short,
|
||||||
|
long,
|
||||||
|
help = "Get all transactions at the specified block height",
|
||||||
|
conflicts_with("to_height"),
|
||||||
|
default_value = "false"
|
||||||
|
)]
|
||||||
|
pub(crate) transactions: bool,
|
||||||
|
#[arg(short, long, help = "Lookup the block height corresponding to a hash value", default_value = "false")]
|
||||||
|
pub(crate) to_height: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Command for Block {
|
||||||
|
type Input = ();
|
||||||
|
type Output = String;
|
||||||
|
|
||||||
|
fn log_span(&self) -> Span {
|
||||||
|
tracing::span!(tracing::Level::INFO, "Leo")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prelude(&self, _context: Context) -> Result<Self::Input> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply(self, _context: Context, _input: Self::Input) -> Result<Self::Output> {
|
||||||
|
// Build custom url to fetch from based on the flags and user's input.
|
||||||
|
let url = if self.latest_height {
|
||||||
|
"block/height/latest".to_string()
|
||||||
|
} else if self.latest_hash {
|
||||||
|
"block/hash/latest".to_string()
|
||||||
|
} else if self.latest {
|
||||||
|
"block/latest".to_string()
|
||||||
|
} else if let Some(range) = self.range {
|
||||||
|
// Make sure the range is composed of valid numbers.
|
||||||
|
is_valid_numerical_input(&range[0])?;
|
||||||
|
is_valid_numerical_input(&range[1])?;
|
||||||
|
|
||||||
|
// Make sure the range is not too large.
|
||||||
|
if range[1].parse::<u32>().unwrap() - range[0].parse::<u32>().unwrap() > 50 {
|
||||||
|
return Err(UtilError::invalid_range().into());
|
||||||
|
}
|
||||||
|
format!("blocks?start={}&end={}", range[0], range[1])
|
||||||
|
} else if self.transactions {
|
||||||
|
is_valid_numerical_input(&self.id.clone().unwrap())?;
|
||||||
|
format!("block/{}/transactions", self.id.unwrap()).to_string()
|
||||||
|
} else if self.to_height {
|
||||||
|
let id = self.id.unwrap();
|
||||||
|
is_valid_hash(&id)?;
|
||||||
|
format!("height/{}", id).to_string()
|
||||||
|
} else if let Some(id) = self.id {
|
||||||
|
is_valid_height_or_hash(&id)?;
|
||||||
|
format!("block/{}", id)
|
||||||
|
} else {
|
||||||
|
unreachable!("All cases are covered")
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(url)
|
||||||
|
}
|
||||||
|
}
|
40
leo/cli/commands/query/committee.rs
Normal file
40
leo/cli/commands/query/committee.rs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
// Copyright (C) 2019-2023 Aleo Systems Inc.
|
||||||
|
// This file is part of the Leo library.
|
||||||
|
|
||||||
|
// The Leo library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// The Leo library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
use clap::Parser;
|
||||||
|
|
||||||
|
/// Query the committee.
|
||||||
|
#[derive(Parser, Debug)]
|
||||||
|
pub struct Committee {}
|
||||||
|
|
||||||
|
impl Command for Committee {
|
||||||
|
type Input = ();
|
||||||
|
type Output = String;
|
||||||
|
|
||||||
|
fn log_span(&self) -> Span {
|
||||||
|
tracing::span!(tracing::Level::INFO, "Leo")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prelude(&self, _context: Context) -> Result<Self::Input> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply(self, _context: Context, _: Self::Input) -> Result<Self::Output> {
|
||||||
|
Ok("/committee/latest".to_string())
|
||||||
|
}
|
||||||
|
}
|
69
leo/cli/commands/query/mempool.rs
Normal file
69
leo/cli/commands/query/mempool.rs
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
// Copyright (C) 2019-2023 Aleo Systems Inc.
|
||||||
|
// This file is part of the Leo library.
|
||||||
|
|
||||||
|
// The Leo library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// The Leo library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
use crate::cli::context::Context;
|
||||||
|
use clap::Parser;
|
||||||
|
|
||||||
|
// Query transactions and transmissions from the memory pool.
|
||||||
|
#[derive(Parser, Debug)]
|
||||||
|
pub struct Mempool {
|
||||||
|
#[arg(
|
||||||
|
short,
|
||||||
|
long,
|
||||||
|
help = "Get the memory pool transactions",
|
||||||
|
default_value = "false",
|
||||||
|
required_unless_present = "transmissions",
|
||||||
|
conflicts_with("transmissions")
|
||||||
|
)]
|
||||||
|
pub(crate) transactions: bool,
|
||||||
|
#[arg(
|
||||||
|
short,
|
||||||
|
long,
|
||||||
|
help = "Get the memory pool transmissions",
|
||||||
|
default_value = "false",
|
||||||
|
required_unless_present = "transactions",
|
||||||
|
conflicts_with("transactions")
|
||||||
|
)]
|
||||||
|
pub(crate) transmissions: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Command for Mempool {
|
||||||
|
type Input = ();
|
||||||
|
type Output = String;
|
||||||
|
|
||||||
|
fn log_span(&self) -> Span {
|
||||||
|
tracing::span!(tracing::Level::INFO, "Leo")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prelude(&self, _context: Context) -> Result<Self::Input> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply(self, _context: Context, _input: Self::Input) -> Result<Self::Output> {
|
||||||
|
// Build custom url to fetch from based on the flags and user's input.
|
||||||
|
let url = if self.transactions {
|
||||||
|
"memoryPool/transactions".to_string()
|
||||||
|
} else if self.transmissions {
|
||||||
|
"memoryPool/transmissions".to_string()
|
||||||
|
} else {
|
||||||
|
unreachable!("All cases are covered")
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(url)
|
||||||
|
}
|
||||||
|
}
|
153
leo/cli/commands/query/mod.rs
Normal file
153
leo/cli/commands/query/mod.rs
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
// Copyright (C) 2019-2023 Aleo Systems Inc.
|
||||||
|
// This file is part of the Leo library.
|
||||||
|
|
||||||
|
// The Leo library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// The Leo library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
mod block;
|
||||||
|
use block::Block;
|
||||||
|
|
||||||
|
mod program;
|
||||||
|
use program::Program;
|
||||||
|
|
||||||
|
mod state_root;
|
||||||
|
use state_root::StateRoot;
|
||||||
|
|
||||||
|
mod committee;
|
||||||
|
use committee::Committee;
|
||||||
|
|
||||||
|
mod mempool;
|
||||||
|
use mempool::Mempool;
|
||||||
|
|
||||||
|
mod peers;
|
||||||
|
use peers::Peers;
|
||||||
|
|
||||||
|
mod transaction;
|
||||||
|
use transaction::Transaction;
|
||||||
|
|
||||||
|
mod utils;
|
||||||
|
use utils::*;
|
||||||
|
|
||||||
|
use leo_errors::UtilError;
|
||||||
|
|
||||||
|
/// Query live data from the Aleo network.
|
||||||
|
#[derive(Parser, Debug)]
|
||||||
|
pub struct Query {
|
||||||
|
#[clap(
|
||||||
|
short,
|
||||||
|
long,
|
||||||
|
global = true,
|
||||||
|
help = "Endpoint to retrieve network state from. Defaults to http://api.explorer.aleo.org/v1.",
|
||||||
|
default_value = "http://api.explorer.aleo.org/v1"
|
||||||
|
)]
|
||||||
|
pub endpoint: String,
|
||||||
|
#[clap(short, long, global = true, help = "Network to use. Defaults to testnet3.", default_value = "testnet3")]
|
||||||
|
pub(crate) network: String,
|
||||||
|
#[clap(subcommand)]
|
||||||
|
command: QueryCommands,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Command for Query {
|
||||||
|
type Input = ();
|
||||||
|
type Output = ();
|
||||||
|
|
||||||
|
fn log_span(&self) -> Span {
|
||||||
|
tracing::span!(tracing::Level::INFO, "Leo")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prelude(&self, _context: Context) -> Result<Self::Input> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply(self, context: Context, _: Self::Input) -> Result<Self::Output> {
|
||||||
|
let output = match self.command {
|
||||||
|
QueryCommands::Block { command } => command.apply(context, ())?,
|
||||||
|
QueryCommands::Transaction { command } => command.apply(context, ())?,
|
||||||
|
QueryCommands::Program { command } => command.apply(context, ())?,
|
||||||
|
QueryCommands::Stateroot { command } => command.apply(context, ())?,
|
||||||
|
QueryCommands::Committee { command } => command.apply(context, ())?,
|
||||||
|
QueryCommands::Mempool { command } => {
|
||||||
|
if self.endpoint == "http://api.explorer.aleo.org/v1" {
|
||||||
|
tracing::warn!(
|
||||||
|
"⚠️ `leo query mempool` is only valid when using a custom endpoint. Specify one using `--endpoint`."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
command.apply(context, ())?
|
||||||
|
}
|
||||||
|
QueryCommands::Peers { command } => {
|
||||||
|
if self.endpoint == "http://api.explorer.aleo.org/v1" {
|
||||||
|
tracing::warn!(
|
||||||
|
"⚠️ `leo query peers` is only valid when using a custom endpoint. Specify one using `--endpoint`."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
command.apply(context, ())?
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Make GET request to retrieve on-chain state.
|
||||||
|
let url = format!("{}/{}/{}", self.endpoint, self.network, output);
|
||||||
|
let response = ureq::get(&url.clone())
|
||||||
|
.set(&format!("X-Aleo-Leo-{}", env!("CARGO_PKG_VERSION")), "true")
|
||||||
|
.call()
|
||||||
|
.map_err(|err| UtilError::failed_to_retrieve_from_endpoint(err, Default::default()))?;
|
||||||
|
if response.status() == 200 {
|
||||||
|
tracing::info!("✅ Successfully retrieved data from '{url}'.\n");
|
||||||
|
// Unescape the newlines.
|
||||||
|
println!("{}\n", response.into_string().unwrap().replace("\\n", "\n"));
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(UtilError::network_error(url, response.status(), Default::default()).into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Parser, Debug)]
|
||||||
|
enum QueryCommands {
|
||||||
|
#[clap(about = "Query block information")]
|
||||||
|
Block {
|
||||||
|
#[clap(flatten)]
|
||||||
|
command: Block,
|
||||||
|
},
|
||||||
|
#[clap(about = "Query transaction information")]
|
||||||
|
Transaction {
|
||||||
|
#[clap(flatten)]
|
||||||
|
command: Transaction,
|
||||||
|
},
|
||||||
|
#[clap(about = "Query program source code and live mapping values")]
|
||||||
|
Program {
|
||||||
|
#[clap(flatten)]
|
||||||
|
command: Program,
|
||||||
|
},
|
||||||
|
#[clap(about = "Query the latest stateroot")]
|
||||||
|
Stateroot {
|
||||||
|
#[clap(flatten)]
|
||||||
|
command: StateRoot,
|
||||||
|
},
|
||||||
|
#[clap(about = "Query the current committee")]
|
||||||
|
Committee {
|
||||||
|
#[clap(flatten)]
|
||||||
|
command: Committee,
|
||||||
|
},
|
||||||
|
#[clap(about = "Query transactions and transmissions from the memory pool")]
|
||||||
|
Mempool {
|
||||||
|
#[clap(flatten)]
|
||||||
|
command: Mempool,
|
||||||
|
},
|
||||||
|
#[clap(about = "Query peer information")]
|
||||||
|
Peers {
|
||||||
|
#[clap(flatten)]
|
||||||
|
command: Peers,
|
||||||
|
},
|
||||||
|
}
|
61
leo/cli/commands/query/peers.rs
Normal file
61
leo/cli/commands/query/peers.rs
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
// Copyright (C) 2019-2023 Aleo Systems Inc.
|
||||||
|
// This file is part of the Leo library.
|
||||||
|
|
||||||
|
// The Leo library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// The Leo library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
use crate::cli::context::Context;
|
||||||
|
use clap::Parser;
|
||||||
|
|
||||||
|
// Query information about network peers.
|
||||||
|
#[derive(Parser, Debug)]
|
||||||
|
pub struct Peers {
|
||||||
|
#[arg(short, long, help = "Get all peer metrics", default_value = "false", conflicts_with("count"))]
|
||||||
|
pub(crate) metrics: bool,
|
||||||
|
#[arg(
|
||||||
|
short,
|
||||||
|
long,
|
||||||
|
help = "Get the count of all participating peers",
|
||||||
|
default_value = "false",
|
||||||
|
conflicts_with("metrics")
|
||||||
|
)]
|
||||||
|
pub(crate) count: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Command for Peers {
|
||||||
|
type Input = ();
|
||||||
|
type Output = String;
|
||||||
|
|
||||||
|
fn log_span(&self) -> Span {
|
||||||
|
tracing::span!(tracing::Level::INFO, "Leo")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prelude(&self, _context: Context) -> Result<Self::Input> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply(self, _context: Context, _input: Self::Input) -> Result<Self::Output> {
|
||||||
|
// Build custom url to fetch from based on the flags and user's input.
|
||||||
|
let url = if self.metrics {
|
||||||
|
"peers/all/metrics".to_string()
|
||||||
|
} else if self.count {
|
||||||
|
"peers/count".to_string()
|
||||||
|
} else {
|
||||||
|
"peers/all".to_string()
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(url)
|
||||||
|
}
|
||||||
|
}
|
67
leo/cli/commands/query/program.rs
Normal file
67
leo/cli/commands/query/program.rs
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
// Copyright (C) 2019-2023 Aleo Systems Inc.
|
||||||
|
// This file is part of the Leo library.
|
||||||
|
|
||||||
|
// The Leo library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// The Leo library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
use clap::Parser;
|
||||||
|
use leo_package::package::Package;
|
||||||
|
|
||||||
|
/// Query program source code and live mapping values.
|
||||||
|
#[derive(Parser, Debug)]
|
||||||
|
pub struct Program {
|
||||||
|
#[clap(name = "NAME", help = "The name of the program to fetch")]
|
||||||
|
pub(crate) name: String,
|
||||||
|
#[arg(
|
||||||
|
short,
|
||||||
|
long,
|
||||||
|
help = "Get all mappings defined in the program",
|
||||||
|
default_value = "false",
|
||||||
|
conflicts_with = "mapping_value"
|
||||||
|
)]
|
||||||
|
pub(crate) mappings: bool,
|
||||||
|
#[arg(short, long, help = "Get the value corresponding to the specified mapping and key.", number_of_values = 2, value_names = &["MAPPING", "KEY"], conflicts_with = "mappings")]
|
||||||
|
pub(crate) mapping_value: Option<Vec<String>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Command for Program {
|
||||||
|
type Input = ();
|
||||||
|
type Output = String;
|
||||||
|
|
||||||
|
fn log_span(&self) -> Span {
|
||||||
|
tracing::span!(tracing::Level::INFO, "Leo")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prelude(&self, _context: Context) -> Result<Self::Input> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply(self, _context: Context, _: Self::Input) -> Result<Self::Output> {
|
||||||
|
// Check that the program name is valid.
|
||||||
|
let program = check_valid_program_name(self.name);
|
||||||
|
// Build custom url to fetch from based on the flags and user's input.
|
||||||
|
let url = if let Some(mapping_info) = self.mapping_value {
|
||||||
|
// Check that the mapping name is valid.
|
||||||
|
Package::<CurrentNetwork>::is_aleo_name_valid(&mapping_info[0]);
|
||||||
|
format!("program/{}/mapping/{}/{}", program, mapping_info[0], mapping_info[1])
|
||||||
|
} else if self.mappings {
|
||||||
|
format!("program/{}/mappings", program)
|
||||||
|
} else {
|
||||||
|
format!("program/{}", program)
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(url)
|
||||||
|
}
|
||||||
|
}
|
40
leo/cli/commands/query/state_root.rs
Normal file
40
leo/cli/commands/query/state_root.rs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
// Copyright (C) 2019-2023 Aleo Systems Inc.
|
||||||
|
// This file is part of the Leo library.
|
||||||
|
|
||||||
|
// The Leo library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// The Leo library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
use clap::Parser;
|
||||||
|
|
||||||
|
/// Query the latest stateroot.
|
||||||
|
#[derive(Parser, Debug)]
|
||||||
|
pub struct StateRoot {}
|
||||||
|
|
||||||
|
impl Command for StateRoot {
|
||||||
|
type Input = ();
|
||||||
|
type Output = String;
|
||||||
|
|
||||||
|
fn log_span(&self) -> Span {
|
||||||
|
tracing::span!(tracing::Level::INFO, "Leo")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prelude(&self, _context: Context) -> Result<Self::Input> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply(self, _context: Context, _: Self::Input) -> Result<Self::Output> {
|
||||||
|
Ok("/stateRoot/latest".to_string())
|
||||||
|
}
|
||||||
|
}
|
68
leo/cli/commands/query/transaction.rs
Normal file
68
leo/cli/commands/query/transaction.rs
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
// Copyright (C) 2019-2023 Aleo Systems Inc.
|
||||||
|
// This file is part of the Leo library.
|
||||||
|
|
||||||
|
// The Leo library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// The Leo library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
use clap::Parser;
|
||||||
|
|
||||||
|
/// Query transaction information.
|
||||||
|
#[derive(Parser, Debug)]
|
||||||
|
pub struct Transaction {
|
||||||
|
#[clap(name = "ID", help = "The id of the transaction to fetch", required_unless_present_any = &["from_program", "from_transition", "from_io", "range"])]
|
||||||
|
pub(crate) id: Option<String>,
|
||||||
|
#[arg(short, long, help = "Get the transaction only if it has been confirmed", default_value = "false", conflicts_with_all(["from_io", "from_transition", "from_program"]))]
|
||||||
|
pub(crate) confirmed: bool,
|
||||||
|
#[arg(value_name = "INPUT_OR_OUTPUT_ID", short, long, help = "Get the transition id that an input or output id occurred in", conflicts_with_all(["from_program", "from_transition", "confirmed", "id"]))]
|
||||||
|
pub(crate) from_io: Option<String>,
|
||||||
|
#[arg(value_name = "TRANSITION_ID", short, long, help = "Get the id of the transaction containing the specified transition", conflicts_with_all(["from_io", "from_program", "confirmed", "id"]))]
|
||||||
|
pub(crate) from_transition: Option<String>,
|
||||||
|
#[arg(value_name = "PROGRAM", short, long, help = "Get the id of the transaction id that the specified program was deployed in", conflicts_with_all(["from_io", "from_transition", "confirmed", "id"]))]
|
||||||
|
pub(crate) from_program: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Command for Transaction {
|
||||||
|
type Input = ();
|
||||||
|
type Output = String;
|
||||||
|
|
||||||
|
fn log_span(&self) -> Span {
|
||||||
|
tracing::span!(tracing::Level::INFO, "Leo")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prelude(&self, _context: Context) -> Result<Self::Input> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply(self, _context: Context, _: Self::Input) -> Result<Self::Output> {
|
||||||
|
// Build custom url to fetch from based on the flags and user's input.
|
||||||
|
let url = if let Some(io_id) = self.from_io {
|
||||||
|
let field = is_valid_field(&io_id)?;
|
||||||
|
format!("find/transitionID/{field}")
|
||||||
|
} else if let Some(transition) = self.from_transition {
|
||||||
|
is_valid_transition_id(&transition)?;
|
||||||
|
format!("find/transactionID/{transition}")
|
||||||
|
} else if let Some(program) = self.from_program {
|
||||||
|
// Check that the program name is valid.
|
||||||
|
format!("find/transactionID/deployment/{}", check_valid_program_name(program))
|
||||||
|
} else if let Some(id) = self.id {
|
||||||
|
is_valid_transaction_id(&id)?;
|
||||||
|
if self.confirmed { format!("transaction/confirmed/{}", id) } else { format!("transaction/{}", id) }
|
||||||
|
} else {
|
||||||
|
unreachable!("All command paths covered.")
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(url)
|
||||||
|
}
|
||||||
|
}
|
94
leo/cli/commands/query/utils.rs
Normal file
94
leo/cli/commands/query/utils.rs
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
// Copyright (C) 2019-2023 Aleo Systems Inc.
|
||||||
|
// This file is part of the Leo library.
|
||||||
|
|
||||||
|
// The Leo library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// The Leo library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
use leo_errors::{LeoError, Result, UtilError};
|
||||||
|
|
||||||
|
use leo_package::package::Package;
|
||||||
|
|
||||||
|
// A valid hash is 61 characters long, with preface "ab1" and all characters lowercase or numbers.
|
||||||
|
pub fn is_valid_hash(hash: &str) -> Result<(), LeoError> {
|
||||||
|
if hash.len() != 61 {
|
||||||
|
Err(UtilError::invalid_input_id_len(hash, "hash").into())
|
||||||
|
} else if !hash.starts_with("ab1") && hash.chars().all(|c| c.is_ascii_lowercase() || c.is_ascii_digit()) {
|
||||||
|
Err(UtilError::invalid_input_id(hash, "hash", "ab1").into())
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A valid transaction id is 61 characters long, with preface "at1" and all characters lowercase or numbers.
|
||||||
|
pub fn is_valid_transaction_id(transaction: &str) -> Result<(), LeoError> {
|
||||||
|
if transaction.len() != 61 {
|
||||||
|
Err(UtilError::invalid_input_id_len(transaction, "transaction").into())
|
||||||
|
} else if !transaction.starts_with("at1")
|
||||||
|
&& transaction.chars().all(|c| c.is_ascii_lowercase() || c.is_ascii_digit())
|
||||||
|
{
|
||||||
|
Err(UtilError::invalid_input_id(transaction, "transaction", "at1").into())
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A valid transition id is 61 characters long, with preface "au1" and all characters lowercase or numbers.
|
||||||
|
pub fn is_valid_transition_id(transition: &str) -> Result<(), LeoError> {
|
||||||
|
if transition.len() != 61 {
|
||||||
|
Err(UtilError::invalid_input_id_len(transition, "transition").into())
|
||||||
|
} else if !transition.starts_with("au1") && transition.chars().all(|c| c.is_ascii_lowercase() || c.is_ascii_digit())
|
||||||
|
{
|
||||||
|
Err(UtilError::invalid_input_id(transition, "transition", "au1").into())
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A valid numerical input is a u32.
|
||||||
|
pub fn is_valid_numerical_input(num: &str) -> Result<(), LeoError> {
|
||||||
|
if num.parse::<u32>().is_err() { Err(UtilError::invalid_numerical_input(num).into()) } else { Ok(()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
// A valid height or hash.
|
||||||
|
pub fn is_valid_height_or_hash(input: &str) -> Result<(), LeoError> {
|
||||||
|
match (is_valid_hash(input), is_valid_numerical_input(input)) {
|
||||||
|
(Ok(_), _) | (_, Ok(_)) => Ok(()),
|
||||||
|
_ => Err(UtilError::invalid_height_or_hash(input).into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks if the string is a valid field, allowing for optional `field` suffix.
|
||||||
|
pub fn is_valid_field(field: &str) -> Result<String, LeoError> {
|
||||||
|
let split = field.split("field").collect::<Vec<&str>>();
|
||||||
|
|
||||||
|
if split.len() == 1 && split[0].chars().all(|c| c.is_numeric()) {
|
||||||
|
Ok(format!("{}field", field))
|
||||||
|
} else if split.len() == 2 && split[0].chars().all(|c| c.is_numeric()) && split[1].is_empty() {
|
||||||
|
Ok(field.to_string())
|
||||||
|
} else {
|
||||||
|
Err(UtilError::invalid_field(field).into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks if the string is a valid program name in Aleo.
|
||||||
|
pub fn check_valid_program_name(name: String) -> String {
|
||||||
|
if name.ends_with(".aleo") {
|
||||||
|
Package::<CurrentNetwork>::is_aleo_name_valid(&name[0..name.len() - 5]);
|
||||||
|
name
|
||||||
|
} else {
|
||||||
|
Package::<CurrentNetwork>::is_aleo_name_valid(&name);
|
||||||
|
format!("{}.aleo", name)
|
||||||
|
}
|
||||||
|
}
|
130
leo/cli/commands/remove.rs
Normal file
130
leo/cli/commands/remove.rs
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
// Copyright (C) 2019-2023 Aleo Systems Inc.
|
||||||
|
// This file is part of the Leo library.
|
||||||
|
|
||||||
|
// The Leo library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// The Leo library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
use leo_retriever::{Dependency, Manifest};
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
/// Remove a dependency from the current package.
|
||||||
|
#[derive(Parser, Debug)]
|
||||||
|
#[clap(name = "leo", author = "The Aleo Team <hello@aleo.org>", version)]
|
||||||
|
pub struct Remove {
|
||||||
|
#[clap(
|
||||||
|
name = "NAME",
|
||||||
|
help = "The dependency name. Ex: `credits.aleo` or `credits`.",
|
||||||
|
required_unless_present = "all"
|
||||||
|
)]
|
||||||
|
pub(crate) name: Option<String>,
|
||||||
|
|
||||||
|
#[clap(short = 'l', long, help = "Path to local dependency")]
|
||||||
|
pub(crate) local: Option<PathBuf>,
|
||||||
|
|
||||||
|
#[clap(short = 'n', long, help = "Name of the network to use", default_value = "testnet3")]
|
||||||
|
pub(crate) network: String,
|
||||||
|
|
||||||
|
#[clap(long, help = "Clear all previous dependencies.", default_value = "false")]
|
||||||
|
pub(crate) all: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Command for Remove {
|
||||||
|
type Input = ();
|
||||||
|
type Output = ();
|
||||||
|
|
||||||
|
fn log_span(&self) -> Span {
|
||||||
|
tracing::span!(tracing::Level::INFO, "Leo")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prelude(&self, _: Context) -> Result<Self::Input> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply(self, context: Context, _: Self::Input) -> Result<Self::Output> {
|
||||||
|
let path = context.dir()?;
|
||||||
|
|
||||||
|
// TODO: Dedup with Add Command. Requires merging utils/retriever/program_context with leo/package as both involve modifying the manifest.
|
||||||
|
// Deserialize the manifest.
|
||||||
|
let program_data: String = std::fs::read_to_string(path.join("program.json"))
|
||||||
|
.map_err(|err| PackageError::failed_to_read_file(path.to_str().unwrap(), err))?;
|
||||||
|
let manifest: Manifest = serde_json::from_str(&program_data)
|
||||||
|
.map_err(|err| PackageError::failed_to_deserialize_manifest_file(path.to_str().unwrap(), err))?;
|
||||||
|
|
||||||
|
let dependencies: Vec<Dependency> = if !self.all {
|
||||||
|
// Make sure the program name is valid.
|
||||||
|
// Allow both `credits.aleo` and `credits` syntax.
|
||||||
|
let name: String = match &self.name {
|
||||||
|
Some(name)
|
||||||
|
if name.ends_with(".aleo")
|
||||||
|
&& Package::<CurrentNetwork>::is_aleo_name_valid(&name[0..name.len() - 5]) =>
|
||||||
|
{
|
||||||
|
name.clone()
|
||||||
|
}
|
||||||
|
Some(name) if Package::<CurrentNetwork>::is_aleo_name_valid(name) => format!("{name}.aleo"),
|
||||||
|
name => return Err(PackageError::invalid_file_name_dependency(name.clone().unwrap()).into()),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut found_match = false;
|
||||||
|
let dep = match manifest.dependencies() {
|
||||||
|
Some(ref dependencies) => dependencies
|
||||||
|
.iter()
|
||||||
|
.filter_map(|dependency| {
|
||||||
|
if dependency.name() == &name {
|
||||||
|
found_match = true;
|
||||||
|
let msg = match (dependency.path(), dependency.network()) {
|
||||||
|
(Some(local_path), _) => format!(
|
||||||
|
"local dependency to `{}` from path `{}`",
|
||||||
|
name,
|
||||||
|
local_path.to_str().unwrap().replace('\"', "")
|
||||||
|
),
|
||||||
|
(_, Some(network)) => {
|
||||||
|
format!("network dependency to `{}` from network `{}`", name, network)
|
||||||
|
}
|
||||||
|
_ => format!("git dependency to `{name}`"),
|
||||||
|
};
|
||||||
|
tracing::warn!("✅ Successfully removed the {msg}.");
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(dependency.clone())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
_ => Vec::new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Throw error if no match is found.
|
||||||
|
if !found_match {
|
||||||
|
return Err(PackageError::dependency_not_found(name).into());
|
||||||
|
}
|
||||||
|
|
||||||
|
dep
|
||||||
|
} else {
|
||||||
|
Vec::new()
|
||||||
|
};
|
||||||
|
|
||||||
|
// Update the manifest file.
|
||||||
|
let new_manifest = Manifest::new(
|
||||||
|
manifest.program(),
|
||||||
|
manifest.version(),
|
||||||
|
manifest.description(),
|
||||||
|
manifest.license(),
|
||||||
|
Some(dependencies),
|
||||||
|
);
|
||||||
|
let new_manifest_data = serde_json::to_string_pretty(&new_manifest)
|
||||||
|
.map_err(|err| PackageError::failed_to_serialize_manifest_file(path.to_str().unwrap(), err))?;
|
||||||
|
std::fs::write(path.join("program.json"), new_manifest_data).map_err(PackageError::failed_to_write_manifest)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
@ -37,8 +37,8 @@ pub struct Package<N: Network> {
|
|||||||
|
|
||||||
impl<N: Network> Package<N> {
|
impl<N: Network> Package<N> {
|
||||||
pub fn new(package_name: &str) -> Result<Self> {
|
pub fn new(package_name: &str) -> Result<Self> {
|
||||||
// Check that the package name is valid.
|
// Check that the package name is a valid Aleo program name.
|
||||||
if !Self::is_package_name_valid(package_name) {
|
if !Self::is_aleo_name_valid(package_name) {
|
||||||
return Err(PackageError::invalid_package_name(package_name).into());
|
return Err(PackageError::invalid_package_name(package_name).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,35 +51,35 @@ impl<N: Network> Package<N> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the package name is valid.
|
/// Returns `true` if it is a valid Aleo name.
|
||||||
///
|
///
|
||||||
/// Package names can only contain ASCII alphanumeric characters and underscores.
|
/// Aleo names can only contain ASCII alphanumeric characters and underscores.
|
||||||
pub fn is_package_name_valid(package_name: &str) -> bool {
|
pub fn is_aleo_name_valid(name: &str) -> bool {
|
||||||
// Check that the package name is nonempty.
|
// Check that the name is nonempty.
|
||||||
if package_name.is_empty() {
|
if name.is_empty() {
|
||||||
tracing::error!("Project names must be nonempty");
|
tracing::error!("Aleo names must be nonempty");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let first = package_name.chars().next().unwrap();
|
let first = name.chars().next().unwrap();
|
||||||
|
|
||||||
// Check that the first character is not an underscore.
|
// Check that the first character is not an underscore.
|
||||||
if first == '_' {
|
if first == '_' {
|
||||||
tracing::error!("Project names cannot begin with an underscore");
|
tracing::error!("Aleo names cannot begin with an underscore");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that the first character is not a number.
|
// Check that the first character is not a number.
|
||||||
if first.is_numeric() {
|
if first.is_numeric() {
|
||||||
tracing::error!("Project names cannot begin with a number");
|
tracing::error!("Aleo names cannot begin with a number");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate and check that the package name is valid.
|
// Iterate and check that the name is valid.
|
||||||
for current in package_name.chars() {
|
for current in name.chars() {
|
||||||
// Check that the package name contains only ASCII alphanumeric or underscores.
|
// Check that the program name contains only ASCII alphanumeric or underscores.
|
||||||
if !current.is_ascii_alphanumeric() && current != '_' {
|
if !current.is_ascii_alphanumeric() && current != '_' {
|
||||||
tracing::error!("Project names must can only contain ASCII alphanumeric characters and underscores.");
|
tracing::error!("Aleo names must can only contain ASCII alphanumeric characters and underscores.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -89,8 +89,8 @@ impl<N: Network> Package<N> {
|
|||||||
|
|
||||||
/// Returns `true` if a package is can be initialized at a given path.
|
/// Returns `true` if a package is can be initialized at a given path.
|
||||||
pub fn can_initialize(package_name: &str, path: &Path) -> bool {
|
pub fn can_initialize(package_name: &str, path: &Path) -> bool {
|
||||||
// Check that the package name is valid.
|
// Check that the package name is a valid Aleo program name.
|
||||||
if !Self::is_package_name_valid(package_name) {
|
if !Self::is_aleo_name_valid(package_name) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,8 +112,8 @@ impl<N: Network> Package<N> {
|
|||||||
|
|
||||||
/// Returns `true` if a package is initialized at the given path
|
/// Returns `true` if a package is initialized at the given path
|
||||||
pub fn is_initialized(package_name: &str, path: &Path) -> bool {
|
pub fn is_initialized(package_name: &str, path: &Path) -> bool {
|
||||||
// Check that the package name is valid.
|
// Check that the package name is a valid Aleo program name.
|
||||||
if !Self::is_package_name_valid(package_name) {
|
if !Self::is_aleo_name_valid(package_name) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,25 +173,25 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_is_package_name_valid() {
|
fn test_is_package_name_valid() {
|
||||||
assert!(Package::<CurrentNetwork>::is_package_name_valid("foo"));
|
assert!(Package::<CurrentNetwork>::is_aleo_name_valid("foo"));
|
||||||
assert!(Package::<CurrentNetwork>::is_package_name_valid("foo_bar"));
|
assert!(Package::<CurrentNetwork>::is_aleo_name_valid("foo_bar"));
|
||||||
assert!(Package::<CurrentNetwork>::is_package_name_valid("foo1"));
|
assert!(Package::<CurrentNetwork>::is_aleo_name_valid("foo1"));
|
||||||
assert!(Package::<CurrentNetwork>::is_package_name_valid("foo_bar___baz_"));
|
assert!(Package::<CurrentNetwork>::is_aleo_name_valid("foo_bar___baz_"));
|
||||||
|
|
||||||
assert!(!Package::<CurrentNetwork>::is_package_name_valid("foo-bar"));
|
assert!(!Package::<CurrentNetwork>::is_aleo_name_valid("foo-bar"));
|
||||||
assert!(!Package::<CurrentNetwork>::is_package_name_valid("foo-bar-baz"));
|
assert!(!Package::<CurrentNetwork>::is_aleo_name_valid("foo-bar-baz"));
|
||||||
assert!(!Package::<CurrentNetwork>::is_package_name_valid("foo-1"));
|
assert!(!Package::<CurrentNetwork>::is_aleo_name_valid("foo-1"));
|
||||||
assert!(!Package::<CurrentNetwork>::is_package_name_valid(""));
|
assert!(!Package::<CurrentNetwork>::is_aleo_name_valid(""));
|
||||||
assert!(!Package::<CurrentNetwork>::is_package_name_valid("-"));
|
assert!(!Package::<CurrentNetwork>::is_aleo_name_valid("-"));
|
||||||
assert!(!Package::<CurrentNetwork>::is_package_name_valid("-foo"));
|
assert!(!Package::<CurrentNetwork>::is_aleo_name_valid("-foo"));
|
||||||
assert!(!Package::<CurrentNetwork>::is_package_name_valid("-foo-"));
|
assert!(!Package::<CurrentNetwork>::is_aleo_name_valid("-foo-"));
|
||||||
assert!(!Package::<CurrentNetwork>::is_package_name_valid("_foo"));
|
assert!(!Package::<CurrentNetwork>::is_aleo_name_valid("_foo"));
|
||||||
assert!(!Package::<CurrentNetwork>::is_package_name_valid("foo--bar"));
|
assert!(!Package::<CurrentNetwork>::is_aleo_name_valid("foo--bar"));
|
||||||
assert!(!Package::<CurrentNetwork>::is_package_name_valid("foo---bar"));
|
assert!(!Package::<CurrentNetwork>::is_aleo_name_valid("foo---bar"));
|
||||||
assert!(!Package::<CurrentNetwork>::is_package_name_valid("foo--bar--baz"));
|
assert!(!Package::<CurrentNetwork>::is_aleo_name_valid("foo--bar--baz"));
|
||||||
assert!(!Package::<CurrentNetwork>::is_package_name_valid("foo---bar---baz"));
|
assert!(!Package::<CurrentNetwork>::is_aleo_name_valid("foo---bar---baz"));
|
||||||
assert!(!Package::<CurrentNetwork>::is_package_name_valid("foo*bar"));
|
assert!(!Package::<CurrentNetwork>::is_aleo_name_valid("foo*bar"));
|
||||||
assert!(!Package::<CurrentNetwork>::is_package_name_valid("foo,bar"));
|
assert!(!Package::<CurrentNetwork>::is_aleo_name_valid("foo,bar"));
|
||||||
assert!(!Package::<CurrentNetwork>::is_package_name_valid("1-foo"));
|
assert!(!Package::<CurrentNetwork>::is_aleo_name_valid("1-foo"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,6 +64,6 @@ impl<N: Network> Env<N> {
|
|||||||
// Initialize a new development private key.
|
// Initialize a new development private key.
|
||||||
let private_key = PrivateKey::<N>::new(rng)?;
|
let private_key = PrivateKey::<N>::new(rng)?;
|
||||||
|
|
||||||
Ok(format!("NETWORK=testnet3\nPRIVATE_KEY={private_key}\n"))
|
Ok(format!("NETWORK=mainnet\nPRIVATE_KEY={private_key}\n"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,3 +61,6 @@ path = "../../compiler/span"
|
|||||||
|
|
||||||
[dev-dependencies.criterion]
|
[dev-dependencies.criterion]
|
||||||
version = "0.5"
|
version = "0.5"
|
||||||
|
|
||||||
|
[dev-dependencies.snarkvm]
|
||||||
|
workspace = true
|
||||||
|
@ -28,6 +28,8 @@ use std::{
|
|||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type CurrentNetwork = snarkvm::prelude::MainnetV0;
|
||||||
|
|
||||||
/// An enum to represent the stage of the Compiler we are benchmarking.
|
/// An enum to represent the stage of the Compiler we are benchmarking.
|
||||||
enum BenchMode {
|
enum BenchMode {
|
||||||
/// Benchmarks parsing.
|
/// Benchmarks parsing.
|
||||||
@ -81,7 +83,7 @@ struct Sample {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A helper function to help create a Leo Compiler struct.
|
/// A helper function to help create a Leo Compiler struct.
|
||||||
fn new_compiler(handler: &Handler) -> Compiler<'_> {
|
fn new_compiler(handler: &Handler) -> Compiler<'_, CurrentNetwork> {
|
||||||
Compiler::new(
|
Compiler::new(
|
||||||
String::from("test"),
|
String::from("test"),
|
||||||
String::from("aleo"),
|
String::from("aleo"),
|
||||||
@ -142,7 +144,7 @@ impl Sample {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Benchmarks `logic(compiler)` where `compiler` is provided.
|
/// Benchmarks `logic(compiler)` where `compiler` is provided.
|
||||||
fn bencher(&self, c: &mut Criterion, mode: &str, mut logic: impl FnMut(Compiler) -> Duration) {
|
fn bencher(&self, c: &mut Criterion, mode: &str, mut logic: impl FnMut(Compiler<CurrentNetwork>) -> Duration) {
|
||||||
c.bench_function(&format!("{mode} {}", self.name), |b| {
|
c.bench_function(&format!("{mode} {}", self.name), |b| {
|
||||||
// Iter custom is used so we can use custom timings around the compiler stages.
|
// Iter custom is used so we can use custom timings around the compiler stages.
|
||||||
// This way we can only time the necessary stage.
|
// This way we can only time the necessary stage.
|
||||||
@ -156,7 +158,12 @@ impl Sample {
|
|||||||
|
|
||||||
/// Benchmarks `logic(compiler)` where `compiler` is provided.
|
/// Benchmarks `logic(compiler)` where `compiler` is provided.
|
||||||
/// Parsing has already been done.
|
/// Parsing has already been done.
|
||||||
fn bencher_after_parse(&self, c: &mut Criterion, mode: &str, mut logic: impl FnMut(Compiler) -> Duration) {
|
fn bencher_after_parse(
|
||||||
|
&self,
|
||||||
|
c: &mut Criterion,
|
||||||
|
mode: &str,
|
||||||
|
mut logic: impl FnMut(Compiler<CurrentNetwork>) -> Duration,
|
||||||
|
) {
|
||||||
self.bencher(c, mode, |mut compiler| {
|
self.bencher(c, mode, |mut compiler| {
|
||||||
let (input, name) = self.data();
|
let (input, name) = self.data();
|
||||||
compiler.parse_program_from_string(input, name).expect("Failed to parse program");
|
compiler.parse_program_from_string(input, name).expect("Failed to parse program");
|
||||||
|
@ -14,17 +14,17 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use snarkvm::{
|
|
||||||
prelude::{Itertools, MainnetV0, Network},
|
|
||||||
synthesizer::program::{CommandTrait, InstructionTrait, Program, ProgramCore},
|
|
||||||
};
|
|
||||||
use std::str::FromStr;
|
|
||||||
type CurrentNetwork = MainnetV0;
|
|
||||||
|
|
||||||
use leo_ast::{Composite, FunctionStub, Identifier, Mapping, ProgramId, Stub};
|
use leo_ast::{Composite, FunctionStub, Identifier, Mapping, ProgramId, Stub};
|
||||||
use leo_errors::UtilError;
|
use leo_errors::UtilError;
|
||||||
use leo_span::Symbol;
|
use leo_span::Symbol;
|
||||||
|
|
||||||
|
use snarkvm::{
|
||||||
|
prelude::{Itertools, Network},
|
||||||
|
synthesizer::program::{CommandTrait, InstructionTrait, Program, ProgramCore},
|
||||||
|
};
|
||||||
|
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
pub fn disassemble<N: Network, Instruction: InstructionTrait<N>, Command: CommandTrait<N>>(
|
pub fn disassemble<N: Network, Instruction: InstructionTrait<N>, Command: CommandTrait<N>>(
|
||||||
program: ProgramCore<N, Instruction, Command>,
|
program: ProgramCore<N, Instruction, Command>,
|
||||||
) -> Stub {
|
) -> Stub {
|
||||||
@ -86,8 +86,8 @@ pub fn disassemble<N: Network, Instruction: InstructionTrait<N>, Command: Comman
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disassemble_from_str(program: &str) -> Result<Stub, UtilError> {
|
pub fn disassemble_from_str<N: Network>(program: &str) -> Result<Stub, UtilError> {
|
||||||
match Program::<CurrentNetwork>::from_str(program) {
|
match Program::<N>::from_str(program) {
|
||||||
Ok(p) => Ok(disassemble(p)),
|
Ok(p) => Ok(disassemble(p)),
|
||||||
Err(_) => Err(UtilError::snarkvm_parsing_error(Default::default())),
|
Err(_) => Err(UtilError::snarkvm_parsing_error(Default::default())),
|
||||||
}
|
}
|
||||||
@ -97,10 +97,10 @@ pub fn disassemble_from_str(program: &str) -> Result<Stub, UtilError> {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use leo_span::symbol::create_session_if_not_set_then;
|
use leo_span::symbol::create_session_if_not_set_then;
|
||||||
use snarkvm::{prelude::MainnetV0, synthesizer::program::Program};
|
use snarkvm::synthesizer::program::Program;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
type CurrentNetwork = MainnetV0;
|
type CurrentNetwork = snarkvm::prelude::MainnetV0;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore]
|
#[ignore]
|
||||||
@ -123,8 +123,8 @@ mod tests {
|
|||||||
fn array_test() {
|
fn array_test() {
|
||||||
create_session_if_not_set_then(|_| {
|
create_session_if_not_set_then(|_| {
|
||||||
let program_from_file =
|
let program_from_file =
|
||||||
fs::read_to_string("../tmp/.aleo/registry/testnet3/zk_bitwise_stack_v0_0_2.aleo").unwrap();
|
fs::read_to_string("../tmp/.aleo/registry/mainnet/zk_bitwise_stack_v0_0_2.aleo").unwrap();
|
||||||
let _program = disassemble_from_str(&program_from_file).unwrap();
|
let _program = disassemble_from_str::<CurrentNetwork>(&program_from_file).unwrap();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,9 @@ license = "GPL-3.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
rust-version = "1.69"
|
rust-version = "1.69"
|
||||||
|
|
||||||
|
[dependencies.snarkvm]
|
||||||
|
workspace = true
|
||||||
|
|
||||||
[dependencies.leo-ast]
|
[dependencies.leo-ast]
|
||||||
version = "1.12.0"
|
version = "1.12.0"
|
||||||
path = "../../compiler/ast"
|
path = "../../compiler/ast"
|
||||||
|
@ -23,11 +23,15 @@ pub use program_context::*;
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use aleo_std::aleo_dir;
|
|
||||||
use leo_span::{symbol::create_session_if_not_set_then, Symbol};
|
use leo_span::{symbol::create_session_if_not_set_then, Symbol};
|
||||||
|
|
||||||
|
use aleo_std::aleo_dir;
|
||||||
|
|
||||||
use serial_test::serial;
|
use serial_test::serial;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
type CurrentNetwork = snarkvm::prelude::MainnetV0;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore]
|
#[ignore]
|
||||||
#[serial]
|
#[serial]
|
||||||
@ -38,8 +42,12 @@ mod tests {
|
|||||||
create_session_if_not_set_then(|_| {
|
create_session_if_not_set_then(|_| {
|
||||||
let build_dir = PathBuf::from(BUILD_DIRECTORY);
|
let build_dir = PathBuf::from(BUILD_DIRECTORY);
|
||||||
let home_dir = PathBuf::from(HOME_DIRECTORY);
|
let home_dir = PathBuf::from(HOME_DIRECTORY);
|
||||||
let mut retriever =
|
let mut retriever = Retriever::<CurrentNetwork>::new(
|
||||||
Retriever::new(Symbol::intern("nested"), &build_dir, &home_dir, "http://0.0.0.0:3030".to_string())
|
Symbol::intern("nested"),
|
||||||
|
&build_dir,
|
||||||
|
&home_dir,
|
||||||
|
"http://0.0.0.0:3030".to_string(),
|
||||||
|
)
|
||||||
.expect("Failed to build retriever");
|
.expect("Failed to build retriever");
|
||||||
retriever.retrieve().expect("failed to retrieve");
|
retriever.retrieve().expect("failed to retrieve");
|
||||||
retriever.prepare_local(Symbol::intern("nested")).expect("failed to prepare local");
|
retriever.prepare_local(Symbol::intern("nested")).expect("failed to prepare local");
|
||||||
@ -57,8 +65,12 @@ mod tests {
|
|||||||
let build_dir = PathBuf::from(BUILD_DIRECTORY);
|
let build_dir = PathBuf::from(BUILD_DIRECTORY);
|
||||||
|
|
||||||
println!("aleo_dir: {:?}", aleo_dir());
|
println!("aleo_dir: {:?}", aleo_dir());
|
||||||
let mut retriever =
|
let mut retriever = Retriever::<CurrentNetwork>::new(
|
||||||
Retriever::new(Symbol::intern("nested"), &build_dir, &aleo_dir(), "http://0.0.0.0:3030".to_string())
|
Symbol::intern("nested"),
|
||||||
|
&build_dir,
|
||||||
|
&aleo_dir(),
|
||||||
|
"http://0.0.0.0:3030".to_string(),
|
||||||
|
)
|
||||||
.expect("Failed to build retriever");
|
.expect("Failed to build retriever");
|
||||||
retriever.retrieve().expect("failed to retrieve");
|
retriever.retrieve().expect("failed to retrieve");
|
||||||
retriever.prepare_local(Symbol::intern("nested")).expect("failed to prepare local");
|
retriever.prepare_local(Symbol::intern("nested")).expect("failed to prepare local");
|
||||||
@ -76,8 +88,12 @@ mod tests {
|
|||||||
create_session_if_not_set_then(|_| {
|
create_session_if_not_set_then(|_| {
|
||||||
let build_dir = PathBuf::from(BUILD_DIRECTORY);
|
let build_dir = PathBuf::from(BUILD_DIRECTORY);
|
||||||
let home_dir = PathBuf::from(HOME_DIRECTORY);
|
let home_dir = PathBuf::from(HOME_DIRECTORY);
|
||||||
let mut retriever =
|
let mut retriever = Retriever::<CurrentNetwork>::new(
|
||||||
Retriever::new(Symbol::intern("simple"), &build_dir, &home_dir, "http://0.0.0.0:3030".to_string())
|
Symbol::intern("simple"),
|
||||||
|
&build_dir,
|
||||||
|
&home_dir,
|
||||||
|
"http://0.0.0.0:3030".to_string(),
|
||||||
|
)
|
||||||
.expect("Failed to build retriever");
|
.expect("Failed to build retriever");
|
||||||
retriever.retrieve().expect("failed to retrieve");
|
retriever.retrieve().expect("failed to retrieve");
|
||||||
retriever.prepare_local(Symbol::intern("simple")).expect("failed to prepare local");
|
retriever.prepare_local(Symbol::intern("simple")).expect("failed to prepare local");
|
||||||
@ -95,8 +111,12 @@ mod tests {
|
|||||||
create_session_if_not_set_then(|_| {
|
create_session_if_not_set_then(|_| {
|
||||||
let build_dir = PathBuf::from(BUILD_DIRECTORY);
|
let build_dir = PathBuf::from(BUILD_DIRECTORY);
|
||||||
let home_dir = PathBuf::from(HOME_DIRECTORY);
|
let home_dir = PathBuf::from(HOME_DIRECTORY);
|
||||||
let mut retriever =
|
let mut retriever = Retriever::<CurrentNetwork>::new(
|
||||||
Retriever::new(Symbol::intern("local_test"), &build_dir, &home_dir, "http://0.0.0.0:3030".to_string())
|
Symbol::intern("local_test"),
|
||||||
|
&build_dir,
|
||||||
|
&home_dir,
|
||||||
|
"http://0.0.0.0:3030".to_string(),
|
||||||
|
)
|
||||||
.expect("Failed to build retriever");
|
.expect("Failed to build retriever");
|
||||||
let _deps = retriever.retrieve().expect("failed to retrieve");
|
let _deps = retriever.retrieve().expect("failed to retrieve");
|
||||||
retriever.prepare_local(Symbol::intern("nested")).expect("failed to prepare local");
|
retriever.prepare_local(Symbol::intern("nested")).expect("failed to prepare local");
|
||||||
|
@ -14,22 +14,23 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::{Location, Network};
|
use crate::{Location, NetworkName};
|
||||||
use leo_span::Symbol;
|
use leo_span::Symbol;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
// Information required to retrieve external program
|
// Information required to retrieve external program
|
||||||
#[derive(Debug, Clone, std::cmp::Eq, PartialEq, Hash, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
|
||||||
pub struct Dependency {
|
pub struct Dependency {
|
||||||
name: String,
|
name: String,
|
||||||
location: Location,
|
location: Location,
|
||||||
network: Option<Network>,
|
network: Option<NetworkName>,
|
||||||
path: Option<PathBuf>,
|
path: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Dependency {
|
impl Dependency {
|
||||||
pub fn new(name: String, location: Location, network: Option<Network>, path: Option<PathBuf>) -> Self {
|
pub fn new(name: String, location: Location, network: Option<NetworkName>, path: Option<PathBuf>) -> Self {
|
||||||
Self { name, location, network, path }
|
Self { name, location, network, path }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,7 +42,7 @@ impl Dependency {
|
|||||||
&self.location
|
&self.location
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn network(&self) -> &Option<Network> {
|
pub fn network(&self) -> &Option<NetworkName> {
|
||||||
&self.network
|
&self.network
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,14 +14,14 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::{Location, Network, ProgramContext};
|
use crate::{Location, NetworkName, ProgramContext};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct LockFileEntry {
|
pub struct LockFileEntry {
|
||||||
name: String,
|
name: String,
|
||||||
network: Option<Network>,
|
network: Option<NetworkName>,
|
||||||
location: Location,
|
location: Location,
|
||||||
path: Option<PathBuf>,
|
path: Option<PathBuf>,
|
||||||
checksum: String,
|
checksum: String,
|
||||||
@ -42,7 +42,7 @@ impl From<&ProgramContext> for LockFileEntry {
|
|||||||
fn from(context: &ProgramContext) -> Self {
|
fn from(context: &ProgramContext) -> Self {
|
||||||
LockFileEntry {
|
LockFileEntry {
|
||||||
name: context.full_name().to_string(),
|
name: context.full_name().to_string(),
|
||||||
network: context.network.clone(), // Direct access as per instruction
|
network: context.network, // Direct access as per instruction
|
||||||
location: context.location().clone(),
|
location: context.location().clone(),
|
||||||
path: context.full_path.clone(), // Direct access as per instruction
|
path: context.full_path.clone(), // Direct access as per instruction
|
||||||
checksum: context.checksum().to_string(),
|
checksum: context.checksum().to_string(),
|
||||||
|
@ -14,23 +14,28 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
pub mod network;
|
|
||||||
|
|
||||||
use indexmap::IndexSet;
|
|
||||||
pub use network::*;
|
|
||||||
use sha2::{Digest, Sha256};
|
|
||||||
use std::path::{Path, PathBuf};
|
|
||||||
pub mod location;
|
pub mod location;
|
||||||
pub use location::Location;
|
pub use location::Location;
|
||||||
pub mod manifest;
|
|
||||||
pub use manifest::*;
|
|
||||||
pub mod dependency;
|
pub mod dependency;
|
||||||
pub use dependency::*;
|
pub use dependency::*;
|
||||||
use leo_ast::Stub;
|
|
||||||
use leo_span::Symbol;
|
|
||||||
|
|
||||||
pub mod lock_file_entry;
|
pub mod lock_file_entry;
|
||||||
pub use lock_file_entry::*;
|
pub use lock_file_entry::*;
|
||||||
|
|
||||||
|
pub mod manifest;
|
||||||
|
pub use manifest::*;
|
||||||
|
|
||||||
|
pub mod network_name;
|
||||||
|
pub use network_name::*;
|
||||||
|
|
||||||
|
use leo_ast::Stub;
|
||||||
|
use leo_span::Symbol;
|
||||||
|
|
||||||
|
use indexmap::IndexSet;
|
||||||
|
use sha2::{Digest, Sha256};
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@ -38,7 +43,7 @@ pub struct ProgramContext {
|
|||||||
name: Symbol,
|
name: Symbol,
|
||||||
full_name: String,
|
full_name: String,
|
||||||
location: Location,
|
location: Location,
|
||||||
network: Option<Network>,
|
network: Option<NetworkName>,
|
||||||
path: Option<PathBuf>,
|
path: Option<PathBuf>,
|
||||||
full_path: Option<PathBuf>,
|
full_path: Option<PathBuf>,
|
||||||
compiled_file_path: Option<PathBuf>,
|
compiled_file_path: Option<PathBuf>,
|
||||||
@ -76,7 +81,7 @@ impl ProgramContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Method to extract 'network', panics if `None`. Only safe to access if location is 'Network'
|
// Method to extract 'network', panics if `None`. Only safe to access if location is 'Network'
|
||||||
pub fn network(&self) -> &Network {
|
pub fn network(&self) -> &NetworkName {
|
||||||
self.network.as_ref().expect("ProgramContext network is None")
|
self.network.as_ref().expect("ProgramContext network is None")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,7 +177,7 @@ impl From<Dependency> for ProgramContext {
|
|||||||
name: Symbol::from(&dependency),
|
name: Symbol::from(&dependency),
|
||||||
full_name: dependency.name().clone(),
|
full_name: dependency.name().clone(),
|
||||||
location: dependency.location().clone(),
|
location: dependency.location().clone(),
|
||||||
network: dependency.network().clone(),
|
network: *dependency.network(),
|
||||||
path: dependency.path().clone(),
|
path: dependency.path().clone(),
|
||||||
full_path: None,
|
full_path: None,
|
||||||
compiled_file_path: None,
|
compiled_file_path: None,
|
||||||
|
@ -18,29 +18,29 @@ use serde::{Deserialize, Serialize};
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
// Retrievable networks for an external program
|
// Retrievable networks for an external program
|
||||||
#[derive(Debug, Clone, std::cmp::Eq, PartialEq, Hash, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize)]
|
||||||
pub enum Network {
|
pub enum NetworkName {
|
||||||
#[serde(rename = "testnet3")]
|
#[serde(rename = "testnet")]
|
||||||
Testnet3,
|
TestnetV0,
|
||||||
#[serde(rename = "mainnet")]
|
#[serde(rename = "mainnet")]
|
||||||
Mainnet,
|
MainnetV0,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&String> for Network {
|
impl From<&String> for NetworkName {
|
||||||
fn from(network: &String) -> Self {
|
fn from(network: &String) -> Self {
|
||||||
match network.to_ascii_lowercase().as_str() {
|
match network.to_ascii_lowercase().as_str() {
|
||||||
"testnet3" => Network::Testnet3,
|
"testnet" => NetworkName::TestnetV0,
|
||||||
"mainnet" => Network::Mainnet,
|
"mainnet" => NetworkName::MainnetV0,
|
||||||
_ => panic!("Invalid network"),
|
_ => panic!("Invalid network"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Network {
|
impl fmt::Display for NetworkName {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Network::Testnet3 => write!(f, "testnet3"),
|
NetworkName::TestnetV0 => write!(f, "testnet"),
|
||||||
Network::Mainnet => write!(f, "mainnet"),
|
NetworkName::MainnetV0 => write!(f, "mainnet"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -14,31 +14,36 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use indexmap::{IndexMap, IndexSet};
|
use crate::{Dependency, Location, LockFileEntry, Manifest, NetworkName, ProgramContext};
|
||||||
|
|
||||||
use leo_ast::Stub;
|
use leo_ast::Stub;
|
||||||
use leo_disassembler::disassemble_from_str;
|
use leo_disassembler::disassemble_from_str;
|
||||||
use leo_errors::UtilError;
|
use leo_errors::UtilError;
|
||||||
use leo_passes::{common::DiGraph, DiGraphError};
|
use leo_passes::{common::DiGraph, DiGraphError};
|
||||||
use leo_span::Symbol;
|
use leo_span::Symbol;
|
||||||
|
|
||||||
use crate::{Dependency, Location, LockFileEntry, Manifest, Network, ProgramContext};
|
use snarkvm::prelude::Network;
|
||||||
|
|
||||||
|
use indexmap::{IndexMap, IndexSet};
|
||||||
use std::{
|
use std::{
|
||||||
fs,
|
fs,
|
||||||
fs::File,
|
fs::File,
|
||||||
io::Read,
|
io::Read,
|
||||||
|
marker::PhantomData,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Retriever is responsible for retrieving external programs
|
// Retriever is responsible for retrieving external programs
|
||||||
pub struct Retriever {
|
pub struct Retriever<N: Network> {
|
||||||
name: Symbol,
|
name: Symbol,
|
||||||
contexts: IndexMap<Symbol, ProgramContext>,
|
contexts: IndexMap<Symbol, ProgramContext>,
|
||||||
project_path: PathBuf,
|
project_path: PathBuf,
|
||||||
registry_path: PathBuf,
|
registry_path: PathBuf,
|
||||||
endpoint: String,
|
endpoint: String,
|
||||||
|
phantom: PhantomData<N>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Retriever {
|
impl<N: Network> Retriever<N> {
|
||||||
// Initialize a new Retriever.
|
// Initialize a new Retriever.
|
||||||
pub fn new(name: Symbol, path: &PathBuf, home: &Path, endpoint: String) -> Result<Self, UtilError> {
|
pub fn new(name: Symbol, path: &PathBuf, home: &Path, endpoint: String) -> Result<Self, UtilError> {
|
||||||
// Starting point is all of the dependencies specified in the main `program.json` file
|
// Starting point is all of the dependencies specified in the main `program.json` file
|
||||||
@ -54,6 +59,7 @@ impl Retriever {
|
|||||||
project_path: path.clone(),
|
project_path: path.clone(),
|
||||||
registry_path: home.join("registry"),
|
registry_path: home.join("registry"),
|
||||||
endpoint: endpoint.clone(),
|
endpoint: endpoint.clone(),
|
||||||
|
phantom: Default::default(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,11 +89,10 @@ impl Retriever {
|
|||||||
// Split into cases based on network dependency or local dependency
|
// Split into cases based on network dependency or local dependency
|
||||||
let nested_dependencies = match cur_context.location() {
|
let nested_dependencies = match cur_context.location() {
|
||||||
Location::Network => {
|
Location::Network => {
|
||||||
let (stub, nested_dependencies) = retrieve_from_network(
|
let (stub, nested_dependencies) = retrieve_from_network::<N>(
|
||||||
&self.project_path,
|
&self.project_path,
|
||||||
&self.registry_path,
|
&self.registry_path,
|
||||||
cur_context.full_name(),
|
cur_context.full_name(),
|
||||||
cur_context.network(),
|
|
||||||
&self.endpoint,
|
&self.endpoint,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
@ -304,7 +309,7 @@ impl Retriever {
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
// Cache the disassembled stub
|
// Cache the disassembled stub
|
||||||
let stub: Stub = disassemble_from_str(&content)?;
|
let stub: Stub = disassemble_from_str::<N>(&content)?;
|
||||||
if cur_context.add_stub(stub.clone()) {
|
if cur_context.add_stub(stub.clone()) {
|
||||||
Err(UtilError::duplicate_dependency_name_error(stub.stub_id.name.name, Default::default()))?;
|
Err(UtilError::duplicate_dependency_name_error(stub.stub_id.name.name, Default::default()))?;
|
||||||
}
|
}
|
||||||
@ -418,15 +423,21 @@ fn retrieve_local(name: &String, path: &PathBuf) -> Result<Vec<Dependency>, Util
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve from network
|
// Retrieve from network
|
||||||
fn retrieve_from_network(
|
fn retrieve_from_network<N: Network>(
|
||||||
project_path: &Path,
|
project_path: &Path,
|
||||||
home_path: &Path,
|
home_path: &Path,
|
||||||
name: &String,
|
name: &String,
|
||||||
network: &Network,
|
|
||||||
endpoint: &String,
|
endpoint: &String,
|
||||||
) -> Result<(Stub, Vec<Dependency>), UtilError> {
|
) -> Result<(Stub, Vec<Dependency>), UtilError> {
|
||||||
|
// Get the network being used.
|
||||||
|
let network = match N::ID {
|
||||||
|
snarkvm::console::network::MainnetV0::ID => NetworkName::MainnetV0,
|
||||||
|
snarkvm::console::network::TestnetV0::ID => NetworkName::TestnetV0,
|
||||||
|
_ => NetworkName::MainnetV0,
|
||||||
|
};
|
||||||
|
|
||||||
// Check if the file is already cached in `~/.aleo/registry/{network}/{program}`
|
// Check if the file is already cached in `~/.aleo/registry/{network}/{program}`
|
||||||
let move_to_path = home_path.join(format!("{network}"));
|
let move_to_path = home_path.join(network.to_string());
|
||||||
let path = move_to_path.join(name.clone());
|
let path = move_to_path.join(name.clone());
|
||||||
let mut file_str: String;
|
let mut file_str: String;
|
||||||
if !path.exists() {
|
if !path.exists() {
|
||||||
@ -439,11 +450,14 @@ fn retrieve_from_network(
|
|||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
// Construct the endpoint for the network.
|
||||||
|
let endpoint = format!("{endpoint}/{network}");
|
||||||
|
|
||||||
// Fetch from network
|
// Fetch from network
|
||||||
println!("Retrieving {} from {:?}.", name, network.clone());
|
println!("Retrieving {name} from {endpoint}.");
|
||||||
file_str = fetch_from_network(endpoint, name, network.clone())?;
|
file_str = fetch_from_network(&endpoint, name)?;
|
||||||
file_str = file_str.replace("\\n", "\n").replace('\"', "");
|
file_str = file_str.replace("\\n", "\n").replace('\"', "");
|
||||||
println!("Successfully retrieved {} from {:?}!", name, network);
|
println!("Successfully retrieved {} from {:?}!", name, endpoint);
|
||||||
|
|
||||||
// Write file to cache
|
// Write file to cache
|
||||||
std::fs::write(path.clone(), file_str.clone().replace("\\n", "\n")).map_err(|err| {
|
std::fs::write(path.clone(), file_str.clone().replace("\\n", "\n")).map_err(|err| {
|
||||||
@ -484,7 +498,7 @@ fn retrieve_from_network(
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
// Disassemble into Stub
|
// Disassemble into Stub
|
||||||
let stub: Stub = disassemble_from_str(&file_str)?;
|
let stub: Stub = disassemble_from_str::<N>(&file_str)?;
|
||||||
|
|
||||||
// Create entry for leo.lock
|
// Create entry for leo.lock
|
||||||
Ok((
|
Ok((
|
||||||
@ -496,7 +510,7 @@ fn retrieve_from_network(
|
|||||||
Dependency::new(
|
Dependency::new(
|
||||||
id.name.name.to_string() + "." + id.network.name.to_string().as_str(),
|
id.name.name.to_string() + "." + id.network.name.to_string().as_str(),
|
||||||
Location::Network,
|
Location::Network,
|
||||||
Some(network.clone()),
|
Some(network),
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@ -504,11 +518,11 @@ fn retrieve_from_network(
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fetch_from_network(endpoint: &String, program: &String, network: Network) -> Result<String, UtilError> {
|
fn fetch_from_network(endpoint: &String, program: &String) -> Result<String, UtilError> {
|
||||||
let url = format!("{}/{}/program/{}", endpoint, network.clone(), program);
|
let url = format!("{}/program/{}", endpoint, program);
|
||||||
let response = ureq::get(&url.clone())
|
let response = ureq::get(&url.clone())
|
||||||
.call()
|
.call()
|
||||||
.map_err(|err| UtilError::failed_to_retrieve_from_endpoint(url.clone(), err, Default::default()))?;
|
.map_err(|err| UtilError::failed_to_retrieve_from_endpoint(err, Default::default()))?;
|
||||||
if response.status() == 200 {
|
if response.status() == 200 {
|
||||||
Ok(response.into_string().unwrap())
|
Ok(response.into_string().unwrap())
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user