mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-09-11 13:56:58 +03:00
Merge pull request #28081 from ProvableHQ/fix/too-many-reqs
[Fix] Network retrieval refactor
This commit is contained in:
commit
b61e2b4733
@ -140,8 +140,9 @@ 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 =
|
let stub = handler.extend_if_error(
|
||||||
handler.extend_if_error(disassemble_from_str::<CurrentNetwork>(&bytecode).map_err(|err| err.into()))?;
|
disassemble_from_str::<CurrentNetwork>(&program_name, &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,8 +184,9 @@ 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 =
|
let stub = handler.extend_if_error(
|
||||||
handler.extend_if_error(disassemble_from_str::<CurrentNetwork>(&bytecode).map_err(|err| err.into()))?;
|
disassemble_from_str::<CurrentNetwork>(&program_name, &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.
|
||||||
|
@ -49,8 +49,8 @@ create_messages!(
|
|||||||
|
|
||||||
@formatted
|
@formatted
|
||||||
snarkvm_parsing_error {
|
snarkvm_parsing_error {
|
||||||
args: (),
|
args: (name: impl Display),
|
||||||
msg: "SnarkVM failure to parse `.aleo` program".to_string(),
|
msg: format!("Failed to parse the source file for `{name}.aleo` into a valid Aleo program."),
|
||||||
help: None,
|
help: None,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
// 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 snarkvm::prelude::{MainnetV0, TestnetV0};
|
||||||
|
|
||||||
mod block;
|
mod block;
|
||||||
use block::Block;
|
use block::Block;
|
||||||
@ -41,6 +42,7 @@ mod utils;
|
|||||||
use utils::*;
|
use utils::*;
|
||||||
|
|
||||||
use leo_errors::UtilError;
|
use leo_errors::UtilError;
|
||||||
|
use leo_retriever::{fetch_from_network, verify_valid_program, NetworkName};
|
||||||
|
|
||||||
/// Query live data from the Aleo network.
|
/// Query live data from the Aleo network.
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
@ -72,49 +74,61 @@ impl Command for Query {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn apply(self, context: Context, _: Self::Input) -> Result<Self::Output> {
|
fn apply(self, context: Context, _: Self::Input) -> Result<Self::Output> {
|
||||||
|
// Parse the network.
|
||||||
|
let network = NetworkName::try_from(self.network.as_str())?;
|
||||||
|
match network {
|
||||||
|
NetworkName::MainnetV0 => handle_query::<MainnetV0>(self, context),
|
||||||
|
NetworkName::TestnetV0 => handle_query::<TestnetV0>(self, context),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A helper function to handle the `query` command.
|
||||||
|
fn handle_query<N: Network>(query: Query, context: Context) -> Result<<Query as Command>::Output> {
|
||||||
let recursive = context.recursive;
|
let recursive = context.recursive;
|
||||||
let output = match self.command {
|
let (program, output) = match query.command {
|
||||||
QueryCommands::Block { command } => command.apply(context, ())?,
|
QueryCommands::Block { command } => (None, command.apply(context, ())?),
|
||||||
QueryCommands::Transaction { command } => command.apply(context, ())?,
|
QueryCommands::Transaction { command } => (None, command.apply(context, ())?),
|
||||||
QueryCommands::Program { command } => command.apply(context, ())?,
|
QueryCommands::Program { command } => {
|
||||||
QueryCommands::Stateroot { command } => command.apply(context, ())?,
|
// Check if querying for program source code.
|
||||||
QueryCommands::Committee { command } => command.apply(context, ())?,
|
let program =
|
||||||
|
if command.mappings || command.mapping_value.is_some() { None } else { Some(command.name.clone()) };
|
||||||
|
(program, command.apply(context, ())?)
|
||||||
|
}
|
||||||
|
QueryCommands::Stateroot { command } => (None, command.apply(context, ())?),
|
||||||
|
QueryCommands::Committee { command } => (None, command.apply(context, ())?),
|
||||||
QueryCommands::Mempool { command } => {
|
QueryCommands::Mempool { command } => {
|
||||||
if self.endpoint == "https://api.explorer.aleo.org/v1" {
|
if query.endpoint == "https://api.explorer.aleo.org/v1" {
|
||||||
tracing::warn!(
|
tracing::warn!(
|
||||||
"⚠️ `leo query mempool` is only valid when using a custom endpoint. Specify one using `--endpoint`."
|
"⚠️ `leo query mempool` is only valid when using a custom endpoint. Specify one using `--endpoint`."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
command.apply(context, ())?
|
(None, command.apply(context, ())?)
|
||||||
}
|
}
|
||||||
QueryCommands::Peers { command } => {
|
QueryCommands::Peers { command } => {
|
||||||
if self.endpoint == "https://api.explorer.aleo.org/v1" {
|
if query.endpoint == "https://api.explorer.aleo.org/v1" {
|
||||||
tracing::warn!(
|
tracing::warn!(
|
||||||
"⚠️ `leo query peers` is only valid when using a custom endpoint. Specify one using `--endpoint`."
|
"⚠️ `leo query peers` is only valid when using a custom endpoint. Specify one using `--endpoint`."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
command.apply(context, ())?
|
(None, command.apply(context, ())?)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Make GET request to retrieve on-chain state.
|
// Make GET request to retrieve on-chain state.
|
||||||
let url = format!("{}/{}/{}", self.endpoint, self.network, output);
|
let url = format!("{}/{}/{output}", query.endpoint, query.network);
|
||||||
let response = ureq::get(&url.clone())
|
let result = fetch_from_network(&url)?;
|
||||||
.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 {
|
|
||||||
// Unescape the newlines.
|
|
||||||
let result = response.into_string().unwrap().replace("\\n", "\n").replace('\"', "");
|
|
||||||
if !recursive {
|
if !recursive {
|
||||||
tracing::info!("✅ Successfully retrieved data from '{url}'.\n");
|
tracing::info!("✅ Successfully retrieved data from '{url}'.\n");
|
||||||
println!("{}\n", result);
|
println!("{}\n", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Verify that the source file parses into a valid Aleo program.
|
||||||
|
if let Some(name) = program {
|
||||||
|
verify_valid_program::<N>(&name, &result)?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
} else {
|
|
||||||
Err(UtilError::network_error(url, response.status(), Default::default()).into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
|
@ -86,10 +86,10 @@ pub fn disassemble<N: Network, Instruction: InstructionTrait<N>, Command: Comman
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disassemble_from_str<N: Network>(program: &str) -> Result<Stub, UtilError> {
|
pub fn disassemble_from_str<N: Network>(name: &str, program: &str) -> Result<Stub, UtilError> {
|
||||||
match Program::<N>::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(name, Default::default())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,7 +124,8 @@ mod tests {
|
|||||||
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/mainnet/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::<CurrentNetwork>(&program_from_file).unwrap();
|
let _program =
|
||||||
|
disassemble_from_str::<CurrentNetwork>("zk_bitwise_stack_v0_0_2", &program_from_file).unwrap();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ 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 snarkvm::prelude::Network;
|
use snarkvm::prelude::{Network, Program};
|
||||||
|
|
||||||
use indexmap::{IndexMap, IndexSet};
|
use indexmap::{IndexMap, IndexSet};
|
||||||
use std::{
|
use std::{
|
||||||
@ -31,6 +31,7 @@ use std::{
|
|||||||
io::Read,
|
io::Read,
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
|
str::FromStr,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Retriever is responsible for retrieving external programs
|
// Retriever is responsible for retrieving external programs
|
||||||
@ -309,7 +310,7 @@ impl<N: Network> Retriever<N> {
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
// Cache the disassembled stub
|
// Cache the disassembled stub
|
||||||
let stub: Stub = disassemble_from_str::<N>(&content)?;
|
let stub: Stub = disassemble_from_str::<N>(&name.to_string(), &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()))?;
|
||||||
}
|
}
|
||||||
@ -439,7 +440,7 @@ fn retrieve_from_network<N: Network>(
|
|||||||
// 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(network.to_string());
|
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 file_str: String;
|
||||||
if !path.exists() {
|
if !path.exists() {
|
||||||
// Create directories along the way if they don't exist
|
// Create directories along the way if they don't exist
|
||||||
std::fs::create_dir_all(&move_to_path).map_err(|err| {
|
std::fs::create_dir_all(&move_to_path).map_err(|err| {
|
||||||
@ -450,13 +451,10 @@ fn retrieve_from_network<N: Network>(
|
|||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// Construct the endpoint for the network.
|
|
||||||
let endpoint = format!("{endpoint}/{network}");
|
|
||||||
|
|
||||||
// Fetch from network
|
// Fetch from network
|
||||||
println!("Retrieving {name} from {endpoint}.");
|
println!("Retrieving {name} from {endpoint} on {network}.");
|
||||||
file_str = fetch_from_network(&endpoint, name)?;
|
file_str = fetch_from_network(&format!("{endpoint}/{network}/program/{}", &name))?;
|
||||||
file_str = file_str.replace("\\n", "\n").replace('\"', "");
|
verify_valid_program::<N>(name, &file_str)?;
|
||||||
println!("Successfully retrieved {} from {:?}!", name, endpoint);
|
println!("Successfully retrieved {} from {:?}!", name, endpoint);
|
||||||
|
|
||||||
// Write file to cache
|
// Write file to cache
|
||||||
@ -498,7 +496,7 @@ fn retrieve_from_network<N: Network>(
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
// Disassemble into Stub
|
// Disassemble into Stub
|
||||||
let stub: Stub = disassemble_from_str::<N>(&file_str)?;
|
let stub: Stub = disassemble_from_str::<N>(name, &file_str)?;
|
||||||
|
|
||||||
// Create entry for leo.lock
|
// Create entry for leo.lock
|
||||||
Ok((
|
Ok((
|
||||||
@ -518,14 +516,23 @@ fn retrieve_from_network<N: Network>(
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fetch_from_network(endpoint: &String, program: &String) -> Result<String, UtilError> {
|
// Fetch the given endpoint url and return the sanitized response.
|
||||||
let url = format!("{}/program/{}", endpoint, program);
|
pub fn fetch_from_network(url: &str) -> Result<String, UtilError> {
|
||||||
let response = ureq::get(&url.clone())
|
let response = ureq::get(url)
|
||||||
|
.set(&format!("X-Aleo-Leo-{}", env!("CARGO_PKG_VERSION")), "true")
|
||||||
.call()
|
.call()
|
||||||
.map_err(|err| UtilError::failed_to_retrieve_from_endpoint(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().replace("\\n", "\n").replace('\"', ""))
|
||||||
} else {
|
} else {
|
||||||
Err(UtilError::network_error(url, response.status(), Default::default()))
|
Err(UtilError::network_error(url, response.status(), Default::default()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Verify that a fetched program is valid aleo instructions.
|
||||||
|
pub fn verify_valid_program<N: Network>(name: &str, program: &str) -> Result<(), UtilError> {
|
||||||
|
match Program::<N>::from_str(program) {
|
||||||
|
Ok(_) => Ok(()),
|
||||||
|
Err(_) => Err(UtilError::snarkvm_parsing_error(name, Default::default())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user