Skip to content

Commit

Permalink
separate open_value_sharing into its own crate
Browse files Browse the repository at this point in the history
  • Loading branch information
lastmjs committed May 17, 2024
1 parent f7ec2e6 commit 681f10c
Show file tree
Hide file tree
Showing 10 changed files with 227 additions and 182 deletions.
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
[workspace]
members = ["src/compiler/rust/canister", "src/compiler/rust/canister_methods"]
members = [
"src/compiler/rust/canister",
"src/compiler/rust/canister_methods",
"src/compiler/rust/open_value_sharing",
]
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ RUN mkdir /global_target_dir

# The following is to pre-compile as many dependencies as possible for Azle projects
# We simply copy over the current Rust setup and do a cargo build
COPY rust/ /azle_rust_dependencies
COPY src/compiler/rust/ /azle_rust_dependencies

RUN touch /azle_rust_dependencies/canister/src/main.js
RUN touch /azle_rust_dependencies/canister/src/candid.did
RUN mkdir /azle_rust_dependencies/canister/src/assets
RUN echo "{\"canister_methods\":{\"queries\":[],\"updates\":[],\"callbacks\":{}},\"env_vars\":[],\"assets\":[]}" > /azle_rust_dependencies/canister/src/compiler_info.json
RUN echo "[workspace]\nmembers = [\"canister\"]\n\n[profile.release]\nopt-level = 'z'" > /azle_rust_dependencies/Cargo.toml
RUN echo "[workspace]\nmembers = [\"canister\", \"canister_methods\", \"open_value_sharing\"]\n\n[profile.release]\nopt-level = 'z'" > /azle_rust_dependencies/Cargo.toml
COPY Cargo.lock /azle_rust_dependencies

WORKDIR /azle_rust_dependencies
Expand Down
4 changes: 3 additions & 1 deletion src/compiler/generate_cargo_toml_files.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ export function generateWorkspaceCargoToml(optLevel: OptLevel): Toml {
[workspace]
members = [
"canister"
"canister",
"canister_methods",
"open_value_sharing"
]
[profile.release]
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/prepare_docker_image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ function buildAndLoadImageWithDockerfile(
}

execSyncPretty(
`podman build -f ${__dirname}/Dockerfile -t ${dockerImageName} ${require.main?.path}`,
`podman build -f ${require.main.path}/Dockerfile -t ${dockerImageName} ${require.main.path}`,
'inherit'
);

Expand Down
9 changes: 9 additions & 0 deletions src/compiler/prepare_rust_staging_area.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@ export function prepareRustStagingArea(
`${canisterPath}/canister_methods`
);

if (!existsSync(`${canisterPath}/open_value_sharing`)) {
mkdirSync(`${canisterPath}/open_value_sharing`);
}

copySync(
`${__dirname}/rust/open_value_sharing`,
`${canisterPath}/open_value_sharing`
);

writeFileSync(`${canisterPath}/canister/src/main.js`, canisterJavaScript);

if (
Expand Down
1 change: 1 addition & 0 deletions src/compiler/rust/canister/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ candid = "0.10.2"
candid_parser = "0.1.2"
ic-stable-structures = "0.6.2"
canister_methods = { path = "../canister_methods" }
open_value_sharing = { path = "../open_value_sharing" }
include_dir = "0.7.3"
slotmap = "=1.0.6"
wasmi = "0.31.2"
Expand Down
181 changes: 4 additions & 177 deletions src/compiler/rust/canister/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use ic_stable_structures::{
DefaultMemoryImpl, StableBTreeMap, Storable,
};
use include_dir::{include_dir, Dir};
use open_value_sharing::open_value_sharing_periodic_payment;
use std::fs;
use wasmedge_quickjs::AsObject;

Expand Down Expand Up @@ -193,185 +194,11 @@ fn run_event_loop(context: &mut wasmedge_quickjs::Context) {
}
}

// TODO do we need error handling??
// TODO it is much more scalable without error handling
// TODO also it's quick and nimble if it's just best effort
// TODO we can also just spawn off timers until they are all done
// TODO we need some way to store state...across upgrades
// TODO the timer always needs to be set across upgrades
// TODO notify runs out after 500 because of the canister outgoing queue
// TODO calling wallet_receive seems to have no limit, takes few cycles, at least within the same subnet
// TODO management canister, which might be across subnets as an emulation, takes the longest
// TODO not sure if there's any practical limit though

// TODO figure out how to get this to work on mainnet and locally well
#[ic_cdk_macros::update]
pub async fn _azle_open_value_sharing_periodic_payment() {
ic_cdk::println!("_azle_open_value_sharing_periodic_payment");

let compiler_info = get_compiler_info("compiler_info.json").unwrap();

let total_periodic_payment_amount = calculate_total_periodic_payment_amount().await;

ic_cdk::println!(
"total_periodic_payment_amount: {}",
total_periodic_payment_amount
);

for (depth, dependency_level) in compiler_info.dependency_info.iter().enumerate() {
ic_cdk::println!("depth: {}", depth);
ic_cdk::println!("dependency_level: {:#?}", dependency_level);

for dependency in dependency_level {
ic_cdk::println!("dependency: {:#?}", dependency);

let dependency_periodic_payment_amount = calculate_dependency_periodic_payment_amount(
dependency,
dependency_level,
depth,
total_periodic_payment_amount,
depth == compiler_info.dependency_info.len() - 1,
);

if dependency.platform == "icp" {
handle_icp_platform(dependency, dependency_periodic_payment_amount).await;
}
}
}
}

// TODO will this work for queries as well?
#[ic_cdk_macros::update]
pub fn _azle_chunk() {}

#[derive(Debug, serde::Serialize, serde::Deserialize)]
struct CanisterMethods {
init: Option<CanisterMethod>,
post_upgrade: Option<CanisterMethod>,
pre_upgrade: Option<CanisterMethod>,
inspect_message: Option<CanisterMethod>,
heartbeat: Option<CanisterMethod>,
queries: Vec<CanisterMethod>,
updates: Vec<CanisterMethod>,
}

#[derive(Debug, serde::Serialize, serde::Deserialize)]
struct CanisterMethod {
name: String,
composite: Option<bool>,
guard_name: Option<String>,
}

#[derive(Debug, serde::Serialize, serde::Deserialize)]
struct CompilerInfo {
canister_methods: CanisterMethods,
env_vars: Vec<(String, String)>,
dependency_info: Vec<Vec<Dependency>>,
}

#[derive(Debug, serde::Serialize, serde::Deserialize)]
struct Dependency {
name: String,
weight: u32,
platform: String,
asset: String,
payment_mechanism: String,
custom: std::collections::HashMap<String, serde_json::Value>,
}

fn get_compiler_info(compiler_info_path: &str) -> Result<CompilerInfo, String> {
let compiler_info_string = fs::read_to_string(compiler_info_path)
.map_err(|err| format!("Error reading {compiler_info_path}: {err}"))?;
let compiler_info: CompilerInfo = serde_json::from_str(&compiler_info_string)
.map_err(|err| format!("Error parsing {compiler_info_path}: {err}"))?;

Ok(compiler_info)
}

// TODO do all of the balance and previous calculation stuff here
async fn calculate_total_periodic_payment_amount() -> u128 {
1_000_000
}

// TODO we also need to take into account the total number of levels
// TODO for example if there is only one level you don't need to cut anything in half
// TODO double-check the weight calculation
fn calculate_dependency_periodic_payment_amount(
dependency: &Dependency,
dependency_level: &Vec<Dependency>,
depth: usize,
total_periodic_payment_amount: u128,
bottom: bool,
) -> u128 {
let adjusted_depth = depth + if bottom { 0 } else { 1 };

let dependency_level_periodic_payment_amount =
total_periodic_payment_amount / 2_u128.pow(adjusted_depth as u32);

ic_cdk::println!(
"dependency_level_periodic_payment_amount: {}",
dependency_level_periodic_payment_amount
);

let total_dependency_level_weight: u32 = dependency_level
.iter()
.map(|dependency| dependency.weight)
.sum();

let dependency_ratio = dependency.weight as f64 / total_dependency_level_weight as f64;

(dependency_level_periodic_payment_amount as f64 * dependency_ratio) as u128
}

async fn handle_icp_platform(dependency: &Dependency, payment_amount: u128) {
if dependency.asset == "cycles" {
handle_icp_platform_asset_cycles(dependency, payment_amount).await;
}
}

async fn handle_icp_platform_asset_cycles(dependency: &Dependency, payment_amount: u128) {
let principal_string = dependency
.custom
.get("principal")
.unwrap()
.as_str()
.unwrap()
.to_string();
let principal = candid::Principal::from_text(principal_string).unwrap();

if dependency.payment_mechanism == "wallet" {
ic_cdk::println!("wallet");

ic_cdk::api::call::call_with_payment128::<(Option<()>,), ()>(
principal,
"wallet_receive",
(None,),
payment_amount,
) // TODO do we need to specify None?
.await
.unwrap();
}

if dependency.payment_mechanism == "deposit" {
ic_cdk::println!("deposit");

ic_cdk::api::management_canister::main::deposit_cycles(
ic_cdk::api::management_canister::main::CanisterIdRecord {
canister_id: principal,
},
payment_amount,
)
.await
.unwrap();
}

ic_cdk::println!("successfully sent {} cycles\n\n", payment_amount);

// TODO add ledger

// TODO should we error out or just log if this is not supported?
// ic_cdk::println!(
// "payment_mechanism \"{}\" is not supported",
// dependency.payment_mechanism
// );
#[ic_cdk_macros::update]
pub async fn _azle_open_value_sharing_periodic_payment() {
open_value_sharing_periodic_payment().await;
}
12 changes: 12 additions & 0 deletions src/compiler/rust/open_value_sharing/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "open_value_sharing"
version = "0.0.0"
edition = "2018"

[dependencies]
serde = "1.0.202"
serde_json = "1.0.107"
candid = "0.10.2"

# TODO this is just for logging
ic-cdk = "0.12.1"
Loading

0 comments on commit 681f10c

Please sign in to comment.