Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

freenet hight level API #1032

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1,128 changes: 556 additions & 572 deletions Cargo.lock

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions crates/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ tracing-subscriber = { optional = true, version = "0.3.16" }
freenet-stdlib = { features = ["net"], workspace = true }
time = "0.3.30"

semver = "*"

home = "0.5.9"


[dev-dependencies]
arbitrary = { features = ["derive"], version = "1" }
chrono = { features = ["arbitrary"], workspace = true }
Expand Down
192 changes: 192 additions & 0 deletions crates/core/src/client_api/commands.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
use std::{fs::File, io::Read, path::PathBuf};

use crate::dev_tool::{
ClientId, Config, ContractStore, DelegateStore, Executor, OperationMode, SecretsStore,
StateStore, Storage,
};
use freenet_stdlib::{
client_api::{ClientRequest, ContractRequest, DelegateRequest},
prelude::*,
};

//use crate::api_request::config::{BaseConfig, PutConfig, UpdateConfig};

const MAX_MEM_CACHE: u32 = 10_000_000;
const DEFAULT_MAX_CONTRACT_SIZE: i64 = 50 * 1024 * 1024;
const DEFAULT_MAX_DELEGATE_SIZE: i64 = 50 * 1024 * 1024;

#[derive(Debug, Clone, clap::Subcommand)]
pub(crate) enum PutType {
/// Puts a new contract
Contract(PutContract),
/// Puts a new delegate
Delegate(PutDelegate),
}

#[derive(clap::Parser, Clone, Debug)]
pub(crate) struct PutContract {
/// A path to a JSON file listing the related contracts.
#[arg(long)]
pub(crate) related_contracts: Option<PathBuf>,
/// A path to the initial state for the contract being published.
#[arg(long)]
pub(crate) state: PathBuf,
}

#[derive(clap::Parser, Clone, Debug)]
pub(crate) struct PutDelegate {
/// Base58 encoded nonce. If empty the default value will be used, this is only allowed in local mode.
#[arg(long, env = "DELEGATE_NONCE", default_value_t = String::new())]
pub(crate) nonce: String,
/// Base58 encoded cipher. If empty the default value will be used, this is only allowed in local mode.
#[arg(long, env = "DELEGATE_CIPHER", default_value_t = String::new())]
pub(crate) cipher: String,
}



/*
pub async fn put(config: PutConfig, other: BaseConfig) -> Result<(), anyhow::Error> {
if config.release {
anyhow::bail!("Cannot publish contracts in the network yet");
}
let params = if let Some(params) = &config.parameters {
let mut buf = vec![];
File::open(params)?.read_to_end(&mut buf)?;
Parameters::from(buf)
} else {
Parameters::from(&[] as &[u8])
};
match &config.package_type {
PutType::Contract(contract) => put_contract(&config, contract, other, params).await,
PutType::Delegate(delegate) => put_delegate(&config, delegate, other, params).await,
}
}
*/




/*async fn put_contract(
config: &PutConfig,
contract_config: &PutContract,
other: BaseConfig,
params: Parameters<'static>,
) -> Result<(), anyhow::Error> {
let contract = ContractContainer::try_from((config.code.as_path(), params))?;
let state = {
let mut buf = vec![];
File::open(&contract_config.state)?.read_to_end(&mut buf)?;
buf.into()
};
let related_contracts = if let Some(_related) = &contract_config.related_contracts {
todo!("use `related` contracts")
} else {
Default::default()
};

println!("Putting contract {}", contract.key());
let request = ContractRequest::Put {
contract,
state,
related_contracts,
}
.into();
execute_command(request, other).await
}

async fn put_delegate(
config: &PutConfig,
delegate_config: &PutDelegate,
other: BaseConfig,
params: Parameters<'static>,
) -> Result<(), anyhow::Error> {
let delegate = DelegateContainer::try_from((config.code.as_path(), params))?;

let (cipher, nonce) = if delegate_config.cipher.is_empty() && delegate_config.nonce.is_empty() {
println!(
"Using default cipher and nonce.
For additional hardening is recommended to use a different cipher and nonce to encrypt secrets in storage.");
(
::freenet_stdlib::client_api::DelegateRequest::DEFAULT_CIPHER,
::freenet_stdlib::client_api::DelegateRequest::DEFAULT_NONCE,
)
} else {
let mut cipher = [0; 32];
bs58::decode(delegate_config.cipher.as_bytes())
.with_alphabet(bs58::Alphabet::BITCOIN)
.onto(&mut cipher)?;

let mut nonce = [0; 24];
bs58::decode(delegate_config.nonce.as_bytes())
.with_alphabet(bs58::Alphabet::BITCOIN)
.onto(&mut nonce)?;
(cipher, nonce)
};

println!("Putting delegate {} ", delegate.key().encode());
let request = DelegateRequest::RegisterDelegate {
delegate,
cipher,
nonce,
}
.into();
execute_command(request, other).await
}
*/

/// send Update Request to the contract at `key` contract.
pub async fn update(
key: String,
delta: Vec<u8>,
contract_data_dir: Option<PathBuf>,
delegate_data_dir: Option<PathBuf>,
secret_data_dir: Option<PathBuf>,
database_dir: Option<PathBuf>
) -> Result<(), anyhow::Error> {
//if config.release {
// anyhow::bail!("Cannot publish contracts in the network yet");
//}
let key = ContractInstanceId::try_from(key)?.into();
println!("Updating contract {key}");
let data = StateDelta::from(delta).into();
let request = ContractRequest::Update { key, data }.into();
execute_command(request, contract_data_dir, delegate_data_dir, secret_data_dir, database_dir).await
}

/// Execute a request command of type ClientRequest.
pub async fn execute_command(
request: ClientRequest<'static>,
contract_data_dir: Option<PathBuf>,
delegate_data_dir: Option<PathBuf>,
secret_data_dir: Option<PathBuf>,
database_dir: Option<PathBuf>
) -> Result<(), anyhow::Error> {
let contracts_data_path = contract_data_dir
.unwrap_or_else(|| Config::conf().contracts_dir());
let delegates_data_path = delegate_data_dir
.unwrap_or_else(|| Config::conf().delegates_dir());
let secrets_data_path = secret_data_dir
.unwrap_or_else(|| Config::conf().secrets_dir());
let database_path = database_dir
.unwrap_or_else(|| Config::conf().db_dir());
let contract_store = ContractStore::new(contracts_data_path, DEFAULT_MAX_CONTRACT_SIZE)?;
let delegate_store = DelegateStore::new(delegates_data_path, DEFAULT_MAX_DELEGATE_SIZE)?;
let secret_store = SecretsStore::new(secrets_data_path)?;
let state_store = StateStore::new(Storage::new(Some(&database_path)).await?, MAX_MEM_CACHE)?;
let rt =
crate::dev_tool::Runtime::build(contract_store, delegate_store, secret_store, false)?;
let mut executor = Executor::new(state_store, || Ok(()), OperationMode::Local, rt, None)
.await
.map_err(|err| anyhow::anyhow!(err))?;

executor
.handle_request(ClientId::FIRST, request, None)
.await
.map_err(|err| {
tracing::error!("{err}");
err
})?;

Ok(())
}
1 change: 1 addition & 0 deletions crates/core/src/client_api/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod commands;
2 changes: 2 additions & 0 deletions crates/core/src/client_api/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod commands;
pub mod simple;
58 changes: 58 additions & 0 deletions crates/core/src/client_api/simple.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
use crate::client_api::commands;

use freenet_stdlib::prelude::ContractInstanceId;
use freenet_stdlib::prelude::StateDelta;
use freenet_stdlib::client_api::ContractRequest;

use home::home_dir;


use crate::dev_tool::{
ClientId, Config, ContractStore, DelegateStore, Executor, OperationMode, SecretsStore,
StateStore, Storage,
};


pub struct API {
port: u32,
}

impl API {
pub fn new(port: u32) -> Self {
API {
port: port
}
}

/// run an UPDATE query to the sit at address `key` with delta `delta`.
pub async fn update(&mut self, key: String, delta: Vec<u8>) -> Result<(), anyhow::Error> {
//if config.release {
// anyhow::bail!("Cannot publish contracts in the network yet");
//}
let key = ContractInstanceId::try_from(key)?.into();
println!("Updating contract {key:?}");
let data = StateDelta::from(delta).into();
println!("Updating contract {data:?}");
let request = ContractRequest::Update { key, data }.into();
println!("Updating contract {request:?}");




//todo: instead use [Some(Config::conf().contracts_dir()), Some(Config::conf().delegates_dir()), Some(Config::conf().secrets_dir()), Some(Config::conf().db_dir())]

let mut contract_path = home::home_dir().expect("Error: Wrong path to home.");
contract_path.push(".local/share/freenet/contracts/local");

let mut delegate_path = home::home_dir().expect("Error: Wrong path to home.");
delegate_path.push(".local/share/freenet/delegates/local");

let mut secret_path = home::home_dir().expect("Error: Wrong path to home.");
secret_path.push(".local/share/freenet/freenet/secrets/local");

let mut database_path = home::home_dir().expect("Error: Wrong path to home.");
database_path.push(".local/share/freenet/db/local");

commands::execute_command(request, Some(contract_path), Some(delegate_path), Some(secret_path), Some(database_path)).await
}
}
3 changes: 3 additions & 0 deletions crates/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,8 @@ pub mod dev_tool {
pub use wasm_runtime::{ContractStore, DelegateStore, Runtime, SecretsStore, StateStore};
}

/// Exports the hight level api for GET, UPDATE, SUBSCRIBE, etc... request from client.
pub mod client_api;

#[cfg(test)]
pub mod test_utils;
2 changes: 1 addition & 1 deletion stdlib
Submodule stdlib updated 0 files