Skip to content

Commit

Permalink
Merge pull request #2 from netsirius/nacho/develop
Browse files Browse the repository at this point in the history
Improve packaging of web files
  • Loading branch information
iduartgomez authored Aug 1, 2022
2 parents 40bef0c + 96c2ae5 commit 9287618
Show file tree
Hide file tree
Showing 10 changed files with 167 additions and 156 deletions.
Binary file not shown.
11 changes: 5 additions & 6 deletions crates/locutus-dev/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,18 @@ A crate for local development purposes.

## Local node example

In order to explore a conract in local mode you need to compile and run the `local-node` executable. The executable requires a number of input parameters, you can run `local-node --help` in order to see the different options. Here is an example running the CLI:
In order to explore a contract in local mode you need to compile and run the `local-node` executable. The executable requires a number of input parameters, you can run `local-node local-node-cli --help` in order to see the different options. Here is an example running the CLI:
```
$ ./local-node --input-file /tmp/input --terminal-output --deser-format json "/home/.../locutus/crates/http-gw/examples/test_web_contract.wasm"
$ ./locutus-dev run-local --input-file /tmp/input --terminal-output --deser-format json "/home/.../locutus/crates/http-gw/examples/test_web_contract.wasm"
```
Follow the instructions under the `help` command when running the tool in console mode to see the different options and commands to interact with the contract.

## Contract state builder example

In order to build an initial state for data or web you need to compile and run the `build_state` executable. The executable requires a number of input parameters, you can run `build_state --help` in order to see the different options. Here are some examples running the CLI:
In order to build an initial state for data or web you need to compile and run the `build_state` executable. The executable requires a number of input parameters, you can run `local-node contract-state-builder --help` in order to see the different options. Here are some examples running the CLI:
```
$ ./build_state --input-path contracts/freenet-microblogging-web/web --output-file contracts/freenet-microblogging-web/encoded_web_state --contract-type web
$ ./locutus-dev build [--input-metadata-path] --input-state-path contracts/freenet-microblogging/view/web --output-file contracts/freenet-microblogging-web/freenet_microblogging_view --contract-type view
$ ./build_state --input-path contracts/freenet-microblogging-data/ --output-file contracts/tfreenet-microblogging-data/encoded_data_state --contract-type data
$ ./locutus-dev build [--input-metadata-path] --input-state-path contracts/freenet-microblogging/model/ --output-file contracts/freenet-microblogging-data/freenet_microblogging_model --contract-type model
```

Follow the instructions under the `help` command when running the tool in console mode to see the different options and commands to interact with the contract.
100 changes: 0 additions & 100 deletions crates/locutus-dev/src/bin/build_state.rs

This file was deleted.

32 changes: 0 additions & 32 deletions crates/locutus-dev/src/bin/local_node.rs

This file was deleted.

125 changes: 125 additions & 0 deletions crates/locutus-dev/src/bin/locutus-dev.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
use clap::Parser;
use tracing_subscriber::EnvFilter;
use byteorder::{BigEndian, WriteBytesExt};
use std::{
fs::File,
io::{Read, Write},
path::PathBuf,
};

use locutus_runtime::locutus_stdlib::web::model::WebModelState;
use locutus_dev::{LocalNodeConfig, StateConfig, SubCommand, ContractType, set_cleanup_on_exit};
use locutus_dev::{user_fn_handler, wasm_runtime, AppState, Config};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
tracing_subscriber::fmt()
.with_env_filter(EnvFilter::from_default_env())
.init();

match Config::parse().sub_command {
SubCommand::RunLocal(contract_cli) => {
run_local_node_client(contract_cli).await
},
SubCommand::Build(state_cli) => {
generate_state(state_cli)
}
}
}

async fn run_local_node_client(cli: LocalNodeConfig) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
if cli.disable_tui_mode {
return Err("CLI mode not yet implemented".into());
}

if cli.clean_exit {
set_cleanup_on_exit()?;
}

let app_state = AppState::new(&cli).await?;
let (sender, receiver) = tokio::sync::mpsc::channel(100);
let runtime = tokio::task::spawn(wasm_runtime(cli.clone(), receiver, app_state.clone()));
let user_fn = user_fn_handler(cli, sender, app_state);
tokio::select! {
res = runtime => { res?? }
res = user_fn => { res? }
};
println!("Shutdown...");
Ok(())
}

fn generate_state(cli: StateConfig) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
let metadata_path: Option<PathBuf> = cli.input_metadata_path;
let state_path: PathBuf = cli.input_state_path;
let dest_file: PathBuf = cli.output_file;

match cli.contract_type {
ContractType::View => {
build_view_state(metadata_path, state_path, dest_file)?;
}
ContractType::Model => {
build_model_state(metadata_path, state_path, dest_file)?;
}
}

Ok(())
}

fn build_view_state(
metadata_path: Option<PathBuf>,
state_path: PathBuf,
dest_file: PathBuf,
) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
tracing::debug!("Bundling `view` state from {state_path:?} into {dest_file:?}");

let mut metadata = vec![];

if let Some(path) = metadata_path {
let mut metadata_f = File::open(path)?;
metadata_f.read_to_end(&mut metadata)?;
}

let view = get_encoded_view(state_path).expect("Failed encoding view");
let model = WebModelState::from_data(metadata, view);

let mut state = File::create(dest_file)?;
state.write_all(model.pack()?.as_slice())?;
Ok(())
}

fn build_model_state(
metadata_path: Option<PathBuf>,
state_path: PathBuf,
dest_file: PathBuf,
) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
tracing::debug!("Bundling `model` contract state from {state_path:?} into {dest_file:?}");

let mut metadata = vec![];
let mut model = vec![];

if let Some(path) = metadata_path {
let mut metadata_f = File::open(path)?;
metadata_f.read_to_end(&mut metadata)?;
}

let mut model_f = File::open(state_path)?;
model_f.read_to_end(&mut model)?;
let model = WebModelState::from_data(metadata, model);

let mut state = File::create(dest_file)?;
state.write_all(model.pack()?.as_slice())?;
Ok(())
}

fn get_encoded_view(
view_path: PathBuf,
) -> Result<Vec<u8>, Box<dyn std::error::Error + Send + Sync + 'static>> {
let mut encoded_view: Vec<u8> = vec![];
let encoder = xz2::write::XzEncoder::new(Vec::new(), 6);
let mut tar = tar::Builder::new(encoder);
tar.append_dir_all(".", &view_path)?;
let encoder_data= tar.into_inner()?;
let mut encoded: Vec<u8> = encoder_data.finish()?;
encoded_view.append(&mut encoded);
Ok(encoded_view)
}
28 changes: 24 additions & 4 deletions crates/locutus-dev/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,22 @@ pub enum ContractType {
Model,
}

#[derive(clap::Subcommand, Clone)]
pub enum SubCommand {
RunLocal(LocalNodeConfig),
Build(StateConfig),

}

#[derive(clap::Parser, Clone)]
#[clap(name = "Locutus Development Environment")]
#[clap(author = "The Freenet Project Inc.")]
#[clap(version = "0.0.1")]
pub struct Config {
#[clap(subcommand)]
pub sub_command: SubCommand,
}

/// A CLI utility for testing out contracts against a Locutus local node.
///
#[derive(clap::Parser, Clone)]
Expand All @@ -29,7 +45,7 @@ pub enum ContractType {
.required(true)
.args(&["output-file", "terminal-output"])
))]
pub struct Config {
pub struct LocalNodeConfig {
/// Cleanups all state which was created locally during execution
#[clap(long, requires = "fmt")]
pub clean_exit: bool,
Expand Down Expand Up @@ -65,13 +81,17 @@ pub struct Config {
pub max_contract_size: i64,
}

/// A CLI utility for build contract states.
///
#[derive(clap::Parser, Clone)]
#[clap(name = "Locutus Contract Development Environment1")]
#[clap(name = "Locutus Contract State Development Environment1")]
#[clap(author = "The Freenet Project Inc.")]
#[clap(version = "0.0.1")]
pub struct StateConfig {
#[clap(long, parse(from_os_str), value_name = "INPUT_PATH")]
pub input_path: PathBuf,
#[clap(long, parse(from_os_str), value_name = "INPUT_METADATA_PATH")]
pub input_metadata_path: Option<PathBuf>,
#[clap(long, parse(from_os_str), value_name = "INPUT_STATE_PATH")]
pub input_state_path: PathBuf,
#[clap(long, parse(from_os_str), value_name = "OUTPUT_PATH")]
pub output_file: PathBuf,
#[clap(long = "contract-type", arg_enum, group = "type", value_name = "TYPE")]
Expand Down
4 changes: 2 additions & 2 deletions crates/locutus-dev/src/executor.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use locutus_node::{ClientId, ClientRequest, HostResponse};

use crate::{config::Config, state::AppState, CommandReceiver, DynError};
use crate::{LocalNodeConfig, state::AppState, CommandReceiver, DynError};

pub async fn wasm_runtime(
_config: Config,
_config: LocalNodeConfig,
mut command_receiver: CommandReceiver,
mut app: AppState,
) -> Result<(), DynError> {
Expand Down
4 changes: 3 additions & 1 deletion crates/locutus-dev/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ mod state;
mod user_events;
pub(crate) mod util;

pub use config::Config;
pub use config::SubCommand;
pub use config::ContractType;
pub use config::Config;
pub use config::LocalNodeConfig;
pub use config::StateConfig;
pub use executor::wasm_runtime;
pub use local_node::LocalNode;
Expand Down
11 changes: 4 additions & 7 deletions crates/locutus-dev/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,18 @@ use locutus_node::SqlitePool;
use locutus_runtime::{ContractStore, StateStore};
use tokio::sync::RwLock;

use crate::{
config::{Config, DeserializationFmt},
set_cleanup_on_exit, DynError, LocalNode,
};
use crate::{config::{DeserializationFmt}, set_cleanup_on_exit, DynError, LocalNode, LocalNodeConfig};

#[derive(Clone)]
pub struct AppState {
pub(crate) local_node: Arc<RwLock<LocalNode>>,
config: Config,
config: LocalNodeConfig,
}

impl AppState {
const MAX_MEM_CACHE: u32 = 10_000_000;

pub async fn new(config: &Config) -> Result<Self, DynError> {
pub async fn new(config: &LocalNodeConfig) -> Result<Self, DynError> {
let tmp_path = std::env::temp_dir().join("locutus").join("contracts");
std::fs::create_dir_all(&tmp_path)?;
let contract_store =
Expand All @@ -36,7 +33,7 @@ impl AppState {
}

pub fn printout_deser<R: AsRef<[u8]> + ?Sized>(&self, data: &R) -> Result<(), std::io::Error> {
fn write_res(config: &Config, pprinted: &str) -> Result<(), std::io::Error> {
fn write_res(config: &LocalNodeConfig, pprinted: &str) -> Result<(), std::io::Error> {
if let Some(p) = &config.output_file {
let mut f = File::create(p)?;
f.write_all(pprinted.as_bytes())?;
Expand Down
Loading

0 comments on commit 9287618

Please sign in to comment.