Merge branch 'develop' into dr/kernel-nested-requests

This commit is contained in:
dr-frmr 2024-02-08 12:23:35 -03:00
commit 027d3d79b5
No known key found for this signature in database
16 changed files with 395 additions and 254 deletions

164
Cargo.lock generated
View File

@ -88,7 +88,7 @@ name = "alias"
version = "0.1.0"
dependencies = [
"anyhow",
"kinode_process_lib 0.5.9",
"kinode_process_lib 0.5.9 (git+https://github.com/kinode-dao/process_lib?tag=v0.5.9-alpha)",
"serde",
"serde_json",
"wit-bindgen",
@ -272,7 +272,7 @@ dependencies = [
"alloy-sol-types",
"anyhow",
"bincode",
"kinode_process_lib 0.5.9",
"kinode_process_lib 0.5.9 (git+https://github.com/kinode-dao/process_lib?tag=v0.5.9-alpha)",
"rand 0.8.5",
"serde",
"serde_json",
@ -809,7 +809,7 @@ name = "cat"
version = "0.1.0"
dependencies = [
"anyhow",
"kinode_process_lib 0.5.9",
"kinode_process_lib 0.5.9 (git+https://github.com/kinode-dao/process_lib?tag=v0.5.9-alpha)",
"serde",
"serde_json",
"wit-bindgen",
@ -871,7 +871,7 @@ dependencies = [
"anyhow",
"base64 0.13.1",
"bincode",
"kinode_process_lib 0.5.9",
"kinode_process_lib 0.5.9 (git+https://github.com/kinode-dao/process_lib?tag=v0.5.9-alpha)",
"pleco",
"serde",
"serde_json",
@ -1611,7 +1611,7 @@ name = "download"
version = "0.1.0"
dependencies = [
"anyhow",
"kinode_process_lib 0.5.9",
"kinode_process_lib 0.5.9 (git+https://github.com/kinode-dao/process_lib?tag=v0.5.9-alpha)",
"serde",
"serde_json",
"wit-bindgen",
@ -1642,7 +1642,7 @@ name = "echo"
version = "0.1.0"
dependencies = [
"anyhow",
"kinode_process_lib 0.5.9",
"kinode_process_lib 0.5.9 (git+https://github.com/kinode-dao/process_lib?tag=v0.5.9-alpha)",
"serde",
"serde_json",
"wit-bindgen",
@ -2002,7 +2002,7 @@ dependencies = [
"serde_json",
"thiserror",
"tokio",
"tokio-tungstenite 0.20.1",
"tokio-tungstenite",
"tracing",
"tracing-futures",
"url",
@ -2214,7 +2214,7 @@ version = "0.2.0"
dependencies = [
"anyhow",
"bincode",
"kinode_process_lib 0.5.9",
"kinode_process_lib 0.5.9 (git+https://github.com/kinode-dao/process_lib?tag=v0.5.9-alpha)",
"rand 0.8.5",
"serde",
"serde_json",
@ -2407,6 +2407,21 @@ dependencies = [
"stable_deref_trait",
]
[[package]]
name = "git2"
version = "0.18.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b3ba52851e73b46a4c3df1d89343741112003f0f6f13beb0dfac9e457c3fdcd"
dependencies = [
"bitflags 2.4.2",
"libc",
"libgit2-sys",
"log",
"openssl-probe",
"openssl-sys",
"url",
]
[[package]]
name = "glob"
version = "0.3.1"
@ -2556,7 +2571,7 @@ checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46"
name = "hi"
version = "0.1.0"
dependencies = [
"kinode_process_lib 0.5.9",
"kinode_process_lib 0.5.9 (git+https://github.com/kinode-dao/process_lib?tag=v0.5.9-alpha)",
"serde",
"serde_json",
"wit-bindgen",
@ -2595,7 +2610,7 @@ version = "0.1.0"
dependencies = [
"anyhow",
"bincode",
"kinode_process_lib 0.5.9",
"kinode_process_lib 0.5.9 (git+https://github.com/kinode-dao/process_lib?tag=v0.5.9-alpha)",
"serde",
"serde_json",
"wit-bindgen",
@ -2870,7 +2885,7 @@ name = "install"
version = "0.1.0"
dependencies = [
"anyhow",
"kinode_process_lib 0.5.9",
"kinode_process_lib 0.5.9 (git+https://github.com/kinode-dao/process_lib?tag=v0.5.9-alpha)",
"serde",
"serde_json",
"wit-bindgen",
@ -3086,7 +3101,7 @@ dependencies = [
[[package]]
name = "kinode"
version = "0.5.3"
version = "0.6.0"
dependencies = [
"aes-gcm",
"anyhow",
@ -3138,7 +3153,7 @@ dependencies = [
"thiserror",
"tokio",
"tokio-stream",
"tokio-tungstenite 0.20.1",
"tokio-tungstenite",
"url",
"uuid 1.7.0",
"walkdir",
@ -3150,28 +3165,11 @@ dependencies = [
[[package]]
name = "kinode_lib"
version = "0.5.3"
version = "0.6.0"
dependencies = [
"lib",
]
[[package]]
name = "kinode_process_lib"
version = "0.5.5"
source = "git+https://github.com/uqbar-dao/process_lib.git?tag=v0.5.5-alpha#722f2dbfbcc4d1bf5da1fa5db137632a3cede44c"
dependencies = [
"anyhow",
"bincode",
"http 1.0.0",
"mime_guess",
"rand 0.8.5",
"serde",
"serde_json",
"thiserror",
"url",
"wit-bindgen",
]
[[package]]
name = "kinode_process_lib"
version = "0.5.9"
@ -3191,18 +3189,36 @@ dependencies = [
"wit-bindgen",
]
[[package]]
name = "kinode_process_lib"
version = "0.5.9"
source = "git+https://github.com/uqbar-dao/process_lib.git?tag=v0.5.9-alpha#5e705086bbd10fde89e11d3e3671f6a618a875a7"
dependencies = [
"anyhow",
"bincode",
"http 1.0.0",
"mime_guess",
"rand 0.8.5",
"serde",
"serde_json",
"thiserror",
"url",
"wit-bindgen",
]
[[package]]
name = "kit"
version = "0.1.0"
source = "git+https://github.com/kinode-dao/kit?rev=15a4681#15a468109d54af140ce2b7313b3d3ed776943d7c"
source = "git+https://github.com/kinode-dao/kit?rev=25b098f#25b098fab136387065d6058162d33c727d277ab8"
dependencies = [
"anyhow",
"base64 0.21.7",
"clap",
"dirs 5.0.1",
"futures-util",
"git2",
"hex",
"kinode_process_lib 0.5.5",
"kinode_process_lib 0.5.9 (git+https://github.com/uqbar-dao/process_lib.git?tag=v0.5.9-alpha)",
"nix",
"regex",
"reqwest",
@ -3212,7 +3228,7 @@ dependencies = [
"serde_json",
"thiserror",
"tokio",
"tokio-tungstenite 0.21.0",
"tokio-tungstenite",
"toml 0.8.9",
"walkdir",
"zip",
@ -3228,7 +3244,7 @@ dependencies = [
"anyhow",
"bincode",
"hex",
"kinode_process_lib 0.5.9",
"kinode_process_lib 0.5.9 (git+https://github.com/kinode-dao/process_lib?tag=v0.5.9-alpha)",
"rmp-serde",
"serde",
"serde_json",
@ -3283,7 +3299,7 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67"
[[package]]
name = "lib"
version = "0.5.3"
version = "0.6.0"
dependencies = [
"ethers",
"ethers-providers",
@ -3305,6 +3321,20 @@ version = "0.2.153"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]]
name = "libgit2-sys"
version = "0.16.2+1.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee4126d8b4ee5c9d9ea891dd875cfdc1e9d0950437179104b183d7d8a74d24e8"
dependencies = [
"cc",
"libc",
"libssh2-sys",
"libz-sys",
"openssl-sys",
"pkg-config",
]
[[package]]
name = "libloading"
version = "0.8.1"
@ -3359,6 +3389,20 @@ dependencies = [
"vcpkg",
]
[[package]]
name = "libssh2-sys"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dc8a030b787e2119a731f1951d6a773e2280c660f8ec4b0f5e1505a386e71ee"
dependencies = [
"cc",
"libc",
"libz-sys",
"openssl-sys",
"pkg-config",
"vcpkg",
]
[[package]]
name = "libz-sys"
version = "1.1.15"
@ -3366,6 +3410,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "037731f5d3aaa87a5675e895b63ddff1a87624bc29f77004ea829809654e48f6"
dependencies = [
"cc",
"libc",
"pkg-config",
"vcpkg",
]
@ -3408,7 +3453,7 @@ version = "0.1.0"
dependencies = [
"anyhow",
"clap",
"kinode_process_lib 0.5.9",
"kinode_process_lib 0.5.9 (git+https://github.com/kinode-dao/process_lib?tag=v0.5.9-alpha)",
"regex",
"serde",
"serde_json",
@ -5490,7 +5535,7 @@ version = "0.1.0"
dependencies = [
"anyhow",
"bincode",
"kinode_process_lib 0.5.9",
"kinode_process_lib 0.5.9 (git+https://github.com/kinode-dao/process_lib?tag=v0.5.9-alpha)",
"rand 0.8.5",
"regex",
"serde",
@ -5504,7 +5549,7 @@ version = "0.1.0"
dependencies = [
"anyhow",
"bincode",
"kinode_process_lib 0.5.9",
"kinode_process_lib 0.5.9 (git+https://github.com/kinode-dao/process_lib?tag=v0.5.9-alpha)",
"serde",
"serde_json",
"thiserror",
@ -5518,7 +5563,7 @@ dependencies = [
"anyhow",
"bincode",
"indexmap 2.2.2",
"kinode_process_lib 0.5.9",
"kinode_process_lib 0.5.9 (git+https://github.com/kinode-dao/process_lib?tag=v0.5.9-alpha)",
"serde",
"serde_json",
"thiserror",
@ -5671,22 +5716,10 @@ dependencies = [
"rustls",
"tokio",
"tokio-rustls",
"tungstenite 0.20.1",
"tungstenite",
"webpki-roots",
]
[[package]]
name = "tokio-tungstenite"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c83b561d025642014097b66e6c1bb422783339e0909e4429cde4749d1990bc38"
dependencies = [
"futures-util",
"log",
"tokio",
"tungstenite 0.21.0",
]
[[package]]
name = "tokio-util"
version = "0.7.10"
@ -5771,7 +5804,7 @@ name = "top"
version = "0.1.0"
dependencies = [
"anyhow",
"kinode_process_lib 0.5.9",
"kinode_process_lib 0.5.9 (git+https://github.com/kinode-dao/process_lib?tag=v0.5.9-alpha)",
"serde",
"serde_json",
"wit-bindgen",
@ -5898,25 +5931,6 @@ dependencies = [
"utf-8",
]
[[package]]
name = "tungstenite"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ef1a641ea34f399a848dea702823bbecfb4c486f911735368f1f137cb8257e1"
dependencies = [
"byteorder",
"bytes",
"data-encoding",
"http 1.0.0",
"httparse",
"log",
"rand 0.8.5",
"sha1",
"thiserror",
"url",
"utf-8",
]
[[package]]
name = "typenum"
version = "1.17.0"
@ -6000,7 +6014,7 @@ name = "uninstall"
version = "0.1.0"
dependencies = [
"anyhow",
"kinode_process_lib 0.5.9",
"kinode_process_lib 0.5.9 (git+https://github.com/kinode-dao/process_lib?tag=v0.5.9-alpha)",
"serde",
"serde_json",
"wit-bindgen",
@ -6154,7 +6168,7 @@ dependencies = [
"serde_urlencoded",
"tokio",
"tokio-stream",
"tokio-tungstenite 0.20.1",
"tokio-tungstenite",
"tokio-util",
"tower-service",
"tracing",

View File

@ -1,7 +1,7 @@
[package]
name = "kinode_lib"
authors = ["KinodeDAO"]
version = "0.5.3"
version = "0.6.0"
edition = "2021"
description = "A general-purpose sovereign cloud computing platform"
homepage = "https://kinode.org"

View File

@ -20,11 +20,6 @@ If you have questions, join the [Kinode discord](https://discord.gg/TCgdca5Bjt)
git clone git@github.com:kinode-dao/kinode.git
# Configure dependency retrieval from GitHub
cd kinode
mkdir .cargo
echo "net.git-fetch-with-cli = true" > .cargo/config
# Get some stuff so we can build Wasm.
cd kinode
@ -34,10 +29,10 @@ rustup target add wasm32-wasi
rustup target add wasm32-wasi --toolchain nightly
cargo install cargo-wasi
# Build the runtime, along with a number of booted-at-startup WASM modules including terminal and key_value
# Build the runtime, along with a number of "distro" WASM modules
# OPTIONAL: --release flag
cargo +nightly build --release -p kinode
cargo +nightly build -p kinode
```
### Boot
@ -47,7 +42,8 @@ Make sure not to use the same home directory for two nodes at once! You can use
TODO: document feature flags `--simulation-mode`
```bash
cargo +nightly run --release -p kinode -- home --rpc wss://eth-sepolia.g.alchemy.com/v2/<your-api-key> --testnet
# OPTIONAL: --release flag
cargo +nightly run -p kinode -- home --rpc wss://<your-api-url> --testnet
```
On boot you will be prompted to navigate to `localhost:8080`. Make sure your ETH wallet is connected to the Sepolia test network. Login should be straightforward, just submit the transactions and follow the flow. If you want to register a new ID you will either need [Sepolia testnet tokens](https://www.infura.io/faucet/sepolia) or an invite code.

2
kinode/Cargo.lock generated
View File

@ -2703,7 +2703,7 @@ dependencies = [
[[package]]
name = "kinode"
version = "0.5.3"
version = "0.6.0"
dependencies = [
"aes-gcm 0.10.2",
"anyhow",

View File

@ -1,7 +1,7 @@
[package]
name = "kinode"
authors = ["KinodeDAO"]
version = "0.5.3"
version = "0.6.0"
edition = "2021"
description = "A general-purpose sovereign cloud computing platform"
homepage = "https://kinode.org"
@ -14,7 +14,7 @@ path = "src/main.rs"
[build-dependencies]
anyhow = "1.0.71"
kit = { git = "https://github.com/kinode-dao/kit", rev = "15a4681" }
kit = { git = "https://github.com/kinode-dao/kit", rev = "25b098f" }
reqwest = { version = "0.11.22", features = ["blocking"] }
sha2 = "0.10"
tokio = { version = "1.28", features = ["macros"] }

View File

@ -1,13 +1,9 @@
use crate::{
DownloadResponse, OnchainPackageMetadata, PackageListing, PackageState, RequestedPackage, State,
};
use crate::{DownloadResponse, PackageListing, PackageState, RequestedPackage, State};
use kinode_process_lib::{
eth::EthAddress,
http::{send_response, IncomingHttpRequest, Method, StatusCode},
print_to_terminal, Address, NodeId, PackageId,
};
use serde_json::json;
use sha3::digest::generic_array::arr::Inc;
use std::collections::HashMap;
/// Actions supported over HTTP:
@ -64,7 +60,7 @@ fn gen_package_info(
"package": id.package().to_string(),
"publisher": id.publisher(),
"installed": match &state {
Some(state) => !state.source_zip.is_some(),
Some(state) => state.installed,
None => false,
},
"metadata_hash": match &listing {

View File

@ -5,7 +5,6 @@ use kinode_process_lib::*;
use kinode_process_lib::{call_init, println};
use serde::{Deserialize, Serialize};
use std::collections::{HashMap, HashSet};
use std::io::Read;
use std::str::FromStr;
wit_bindgen::generate!({
@ -227,12 +226,6 @@ fn handle_remote_request(
}
}
let file_name = format!("/{}.zip", package_id);
if let Some(zip_bytes) = package_state.source_zip {
match spawn_transfer(&our, &file_name, Some(zip_bytes), 60, &source) {
Ok(()) => return Resp::RemoteResponse(RemoteResponse::DownloadApproved),
Err(_e) => return Resp::RemoteResponse(RemoteResponse::DownloadDenied),
}
}
// get the .zip from VFS and attach as blob to response
let file_path = format!("/{}/pkg/{}.zip", package_id, package_id);
let Ok(Ok(_)) = Request::to(("our", "vfs", "distro", "sys"))
@ -274,13 +267,14 @@ fn handle_local_request(
let package_state = PackageState {
mirrored_from: Some(our.node.clone()),
our_version,
source_zip: Some(blob.bytes),
installed: false,
caps_approved: true, // TODO see if we want to auto-approve local installs
mirroring: *mirror,
auto_update: false, // can't auto-update a local package
metadata: None, // TODO
};
let Ok(()) = state.add_downloaded_package(package, package_state, true) else {
let Ok(()) = state.add_downloaded_package(package, package_state, Some(blob.bytes))
else {
return LocalResponse::NewPackageResponse(NewPackageResponse::Failure);
};
LocalResponse::NewPackageResponse(NewPackageResponse::Success)
@ -447,13 +441,13 @@ fn handle_receive_download(
PackageState {
mirrored_from: Some(requested_package.from),
our_version: download_hash,
source_zip: Some(blob.bytes),
installed: false,
caps_approved: false,
mirroring: requested_package.mirror,
auto_update: requested_package.auto_update,
metadata: None, // TODO
},
true,
Some(blob.bytes),
)
}
@ -544,13 +538,6 @@ pub fn handle_install(
format!("/{}", entry.process_wasm_path)
};
let wasm_path = format!("{}{}", drive_path, wasm_path);
// build initial caps
let mut initial_capabilities: HashSet<kt::Capability> = HashSet::new();
if entry.request_networking {
initial_capabilities.insert(kt::de_wit_capability(networking_cap.clone()));
}
initial_capabilities.insert(kt::de_wit_capability(read_cap.clone()));
initial_capabilities.insert(kt::de_wit_capability(write_cap.clone()));
let process_id = format!("{}:{}", entry.process_name, package_id);
let Ok(parsed_new_process_id) = process_id.parse::<ProcessId>() else {
return Err(anyhow::anyhow!("app store: invalid process id!"));
@ -568,17 +555,37 @@ pub fn handle_install(
action: vfs::VfsAction::Read,
})?)
.send_and_await_response(5)??;
Request::new()
.target(("our", "kernel", "distro", "sys"))
.body(serde_json::to_vec(&kt::KernelCommand::InitializeProcess {
id: parsed_new_process_id.clone(),
wasm_bytes_handle: wasm_path,
wit_version: None,
on_exit: entry.on_exit.clone(),
initial_capabilities: HashSet::new(),
public: entry.public,
})?)
.inherit(true)
.send_and_await_response(5)??;
// build initial caps
let mut requested_capabilities: Vec<kt::Capability> = vec![];
for value in &entry.request_capabilities {
let mut capability = None;
match value {
serde_json::Value::String(process_name) => {
if let Ok(parsed_process_id) = process_name.parse::<ProcessId>() {
capability = get_capability(
&Address {
requested_capabilities.push(kt::Capability {
issuer: Address {
node: our.node.clone(),
process: parsed_process_id.clone(),
},
"\"messaging\"".into(),
params: "\"messaging\"".into(),
});
} else {
println!(
"app-store: invalid cap: {} for {} to request!",
value.to_string(),
package_id
);
}
}
@ -590,12 +597,18 @@ pub fn handle_install(
.parse::<ProcessId>()
{
if let Some(params) = map.get("params") {
capability = get_capability(
&Address {
requested_capabilities.push(kt::Capability {
issuer: Address {
node: our.node.clone(),
process: parsed_process_id.clone(),
},
&params.to_string(),
params: params.to_string(),
});
} else {
println!(
"app-store: invalid cap: {} for {} to request!",
value.to_string(),
package_id
);
}
}
@ -605,27 +618,19 @@ pub fn handle_install(
continue;
}
}
if let Some(cap) = capability {
initial_capabilities.insert(kt::de_wit_capability(cap));
} else {
println!(
"app-store: no cap: {} for {} to request!",
value.to_string(),
package_id
);
}
}
Request::to(("our", "kernel", "distro", "sys"))
.body(serde_json::to_vec(&kt::KernelCommand::InitializeProcess {
id: parsed_new_process_id.clone(),
wasm_bytes_handle: wasm_path,
wit_version: None,
on_exit: entry.on_exit.clone(),
initial_capabilities,
public: entry.public,
if entry.request_networking {
requested_capabilities.push(kt::de_wit_capability(networking_cap.clone()));
}
requested_capabilities.push(kt::de_wit_capability(read_cap.clone()));
requested_capabilities.push(kt::de_wit_capability(write_cap.clone()));
Request::new()
.target(("our", "kernel", "distro", "sys"))
.body(serde_json::to_vec(&kt::KernelCommand::GrantCapabilities {
target: parsed_new_process_id.clone(),
capabilities: requested_capabilities,
})?)
.inherit(true)
.send_and_await_response(5)??;
.send()?;
}
// THEN, *after* all processes have been initialized, grant caps in manifest
// TODO for both grants and requests: make the vector of caps
@ -693,5 +698,9 @@ pub fn handle_install(
))?)
.send_and_await_response(5)??;
}
// finally set the package as installed
state.update_downloaded_package(package_id, |package_state| {
package_state.installed = true;
});
Ok(())
}

View File

@ -1,4 +1,3 @@
use alloy_primitives::FixedBytes;
use alloy_rpc_types::Log;
use alloy_sol_types::{sol, SolEvent};
use kinode_process_lib::kernel_types as kt;
@ -85,8 +84,7 @@ pub struct PackageState {
pub mirrored_from: Option<NodeId>,
/// the version of the package we have downloaded
pub our_version: String,
/// if None, package already installed. if Some, the source file
pub source_zip: Option<Vec<u8>>,
pub installed: bool,
pub caps_approved: bool,
/// are we serving this package to others?
pub mirroring: bool,
@ -174,13 +172,52 @@ impl State {
&mut self,
package_id: &PackageId,
package_state: PackageState,
save_to_vfs: bool,
package_bytes: Option<Vec<u8>>,
) -> anyhow::Result<()> {
if let Some(package_bytes) = package_bytes {
let drive_name = format!("/{package_id}/pkg");
let blob = LazyLoadBlob {
mime: Some("application/zip".to_string()),
bytes: package_bytes,
};
// create a new drive for this package in VFS
// this is possible because we have root access
Request::to(("our", "vfs", "distro", "sys"))
.body(serde_json::to_vec(&vfs::VfsRequest {
path: drive_name.clone(),
action: vfs::VfsAction::CreateDrive,
})?)
.send_and_await_response(5)??;
// convert the zip to a new package drive
let response = Request::to(("our", "vfs", "distro", "sys"))
.body(serde_json::to_vec(&vfs::VfsRequest {
path: drive_name.clone(),
action: vfs::VfsAction::AddZip,
})?)
.blob(blob.clone())
.send_and_await_response(5)??;
let vfs::VfsResponse::Ok = serde_json::from_slice::<vfs::VfsResponse>(response.body())?
else {
return Err(anyhow::anyhow!(
"cannot add NewPackage: do not have capability to access vfs"
));
};
// save the zip file itself in VFS for sharing with other nodes
// call it <package_id>.zip
let zip_path = format!("{}/{}.zip", drive_name, package_id);
Request::to(("our", "vfs", "distro", "sys"))
.body(serde_json::to_vec(&vfs::VfsRequest {
path: zip_path,
action: vfs::VfsAction::Write,
})?)
.blob(blob)
.send_and_await_response(5)??;
}
self.downloaded_packages
.insert(package_id.to_owned(), package_state);
if save_to_vfs {
self.save_downloaded_package_in_vfs(package_id)?;
}
crate::set_state(&bincode::serialize(self)?);
Ok(())
}
@ -267,74 +304,19 @@ impl State {
PackageState {
mirrored_from: None,
our_version,
source_zip: None, // since it's already installed
installed: true,
caps_approved: true, // since it's already installed this must be true
mirroring: false,
auto_update: false,
metadata: None,
},
false,
None,
)?
}
}
Ok(())
}
/// saves state
fn save_downloaded_package_in_vfs(&mut self, package_id: &PackageId) -> anyhow::Result<()> {
let Some(mut package_state) = self.get_downloaded_package(package_id) else {
return Err(anyhow::anyhow!("no package state"));
};
let Some(zip_bytes) = package_state.source_zip else {
return Err(anyhow::anyhow!("no source zip"));
};
let drive_name = format!("/{package_id}/pkg");
let blob = LazyLoadBlob {
mime: Some("application/zip".to_string()),
bytes: zip_bytes,
};
// create a new drive for this package in VFS
// this is possible because we have root access
Request::to(("our", "vfs", "distro", "sys"))
.body(serde_json::to_vec(&vfs::VfsRequest {
path: drive_name.clone(),
action: vfs::VfsAction::CreateDrive,
})?)
.send_and_await_response(5)??;
// convert the zip to a new package drive
let response = Request::to(("our", "vfs", "distro", "sys"))
.body(serde_json::to_vec(&vfs::VfsRequest {
path: drive_name.clone(),
action: vfs::VfsAction::AddZip,
})?)
.blob(blob.clone())
.send_and_await_response(5)??;
let vfs::VfsResponse::Ok = serde_json::from_slice::<vfs::VfsResponse>(response.body())?
else {
return Err(anyhow::anyhow!(
"cannot add NewPackage: do not have capability to access vfs"
));
};
// save the zip file itself in VFS for sharing with other nodes
// call it <package_id>.zip
let zip_path = format!("{}/{}.zip", drive_name, package_id);
Request::to(("our", "vfs", "distro", "sys"))
// .inherit(true) is this needed?
.body(serde_json::to_vec(&vfs::VfsRequest {
path: zip_path,
action: vfs::VfsAction::Write,
})?)
.blob(blob)
.send_and_await_response(5)??;
package_state.source_zip = None;
crate::set_state(&bincode::serialize(self)?);
Ok(())
}
pub fn uninstall(&mut self, package_id: &PackageId) -> anyhow::Result<()> {
let drive_path = format!("/{package_id}/pkg");
Request::new()
@ -459,7 +441,16 @@ impl State {
"app store: got log with no matching listing"
))?;
let metadata = fetch_metadata(&metadata_url, &metadata_hash).ok();
let metadata = match fetch_metadata(&metadata_url, &metadata_hash) {
Ok(metadata) => Some(metadata),
Err(e) => {
crate::print_to_terminal(
1,
&format!("app store: failed to fetch metadata: {e:?}"),
);
None
}
};
current_listing.metadata_hash = metadata_hash;
current_listing.metadata = metadata;
@ -557,12 +548,14 @@ fn fetch_metadata(
return Err(anyhow::anyhow!("no blob"));
};
let hash = generate_metadata_hash(&body.bytes);
if &hash == &metadata_hash.replace("0x", "") {
if &hash == metadata_hash {
Ok(serde_json::from_slice::<OnchainPackageMetadata>(
&body.bytes,
)?)
} else {
Err(anyhow::anyhow!("metadata hash mismatch"))
Err(anyhow::anyhow!(
"metadata hash mismatch: got {hash}, expected {metadata_hash}"
))
}
}
@ -571,7 +564,7 @@ fn generate_metadata_hash(metadata: &[u8]) -> String {
use sha3::{Digest, Keccak256};
let mut hasher = Keccak256::new();
hasher.update(metadata);
format!("{:x}", hasher.finalize())
format!("0x{:x}", hasher.finalize())
}
/// generate a Keccak-256 hash of the package name and publisher (match onchain)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

File diff suppressed because one or more lines are too long

View File

@ -9,7 +9,7 @@
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport"
content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1.00001, viewport-fit=cover" />
<link href='https://fonts.googleapis.com/css?family=Montserrat' rel='stylesheet'>
<link href='https://fonts.googleapis.com/css?family=Montserrat' rel='stylesheet'>
<style>
:root {
@ -197,7 +197,8 @@
<h3 id="uq-name">Welcome ${our}!</h3>
<h4>Apps:</h4>
<!-- <a id="file-transfer" href="/file-transfer">File Transfer</a> -->
<a id="app-store" href="/main:app_store:sys/">App Store</a>
<br />
<a id="chess" href="/chess:chess:sys/">Chess</a>
</div>
<script>window.ourName = window.our = '${our}'</script>
@ -215,8 +216,8 @@
document.addEventListener('DOMContentLoaded', function () {
// const fileTransferLink = document.getElementById('file-transfer')
// fileTransferLink.attributes.href.value = (window.location.pathname + fileTransferLink.attributes.href.value).replace('//', '/')
const chessLink = document.getElementById('chess')
chessLink.attributes.href.value = (window.location.pathname + chessLink.attributes.href.value).replace('//', '/')
// const chessLink = document.getElementById('chess')
// chessLink.attributes.href.value = (window.location.pathname + chessLink.attributes.href.value).replace('//', '/')
// const webSocket = new WebSocket('ws://' + window.location.host) // Handle proxying later
// webSocket.onopen = () => {

View File

@ -52,7 +52,7 @@
},
"m.wasm": {
"root": true,
"public": false,
"public": true,
"request_networking": true
}
}

View File

@ -2,8 +2,8 @@ use anyhow::anyhow;
use kinode_process_lib::kernel_types as kt;
use kinode_process_lib::kinode::process::standard as wit;
use kinode_process_lib::{
get_blob, get_capability, get_typed_state, our_capabilities, println, set_state, vfs, Address,
Capability, PackageId, ProcessId, Request,
get_blob, get_typed_state, our_capabilities, print_to_terminal, println, set_state, vfs,
Address, Capability, PackageId, ProcessId, Request,
};
use regex::Regex;
use serde::{Deserialize, Serialize};
@ -205,13 +205,6 @@ fn handle_run(
};
let wasm_path = format!("{}{}", drive_path, wasm_path);
// build initial caps
let mut initial_capabilities: HashSet<kt::Capability> = HashSet::new();
if entry.request_networking {
initial_capabilities.insert(kt::de_wit_capability(Capability {
issuer: Address::new(&our.node, ("kernel", "distro", "sys")),
params: "\"network\"".to_string(),
}));
}
let process_id = format!("{}:{}", rand::random::<u64>(), package); // all scripts are given random process IDs
let Ok(parsed_new_process_id) = process_id.parse::<ProcessId>() else {
return Err(anyhow::anyhow!("app store: invalid process id!"));
@ -224,19 +217,31 @@ fn handle_run(
action: vfs::VfsAction::Read,
})?)
.send_and_await_response(5)??;
Request::new()
.target(("our", "kernel", "distro", "sys"))
.body(serde_json::to_vec(&kt::KernelCommand::InitializeProcess {
id: parsed_new_process_id.clone(),
wasm_bytes_handle: wasm_path.clone(),
wit_version: None,
on_exit: kt::OnExit::None, // TODO this should send a message back to runner:script:sys so that it can Drop capabilities
initial_capabilities: HashSet::new(),
public: entry.public,
})?)
.inherit(true)
.send_and_await_response(5)??;
let mut requested_caps: Vec<kt::Capability> = vec![];
if let Some(to_request) = &entry.request_capabilities {
for value in to_request {
let mut capability = None;
match value {
serde_json::Value::String(process_name) => {
if let Ok(parsed_process_id) = process_name.parse::<ProcessId>() {
capability = get_capability(
&Address {
requested_caps.push(kt::Capability {
issuer: Address {
node: our.node.clone(),
process: parsed_process_id.clone(),
},
"\"messaging\"".into(),
);
params: "\"messaging\"".into(),
});
}
}
serde_json::Value::Object(map) => {
@ -247,13 +252,13 @@ fn handle_run(
.parse::<ProcessId>()
{
if let Some(params) = map.get("params") {
capability = get_capability(
&Address {
requested_caps.push(kt::Capability {
issuer: Address {
node: our.node.clone(),
process: parsed_process_id.clone(),
},
&params.to_string(),
);
params: params.to_string(),
});
}
}
}
@ -262,36 +267,44 @@ fn handle_run(
continue;
}
}
if let Some(cap) = capability {
initial_capabilities.insert(kt::de_wit_capability(cap));
} else {
println!(
"runner: no cap: {}, for {} to request!",
value.to_string(),
package
);
}
}
}
if entry.request_networking {
requested_caps.push(kt::de_wit_capability(Capability {
issuer: Address::new(&our.node, ("kernel", "distro", "sys")),
params: "\"network\"".to_string(),
}));
}
if entry.root {
for cap in our_capabilities() {
requested_caps.push(kt::de_wit_capability(cap.clone()));
}
}
print_to_terminal(
1,
&format!(
"{}: Process {{\n wasm_bytes_handle: {},\n wit_version: {},\n on_exit: {:?},\n public: {}\n capabilities: {}\n}}",
parsed_new_process_id.clone(),
wasm_path.clone(),
"None",
kt::OnExit::None,
entry.public,
{
let mut caps_string = "[".to_string();
for cap in requested_caps.iter() {
caps_string += &format!("\n {}({})", cap.issuer.to_string(), cap.params);
}
caps_string + "\n ]"
},
),
);
Request::new()
.target(("our", "kernel", "distro", "sys"))
.body(serde_json::to_vec(&kt::KernelCommand::InitializeProcess {
id: parsed_new_process_id.clone(),
wasm_bytes_handle: wasm_path,
wit_version: None,
on_exit: kt::OnExit::None, // TODO this should send a message back to runner:script:sys so that it can Drop capabilities
initial_capabilities: if entry.root {
our_capabilities()
.iter()
.map(|wit: &kinode_process_lib::Capability| kt::de_wit_capability(wit.clone()))
.collect()
} else {
initial_capabilities
},
public: entry.public,
.body(serde_json::to_vec(&kt::KernelCommand::GrantCapabilities {
target: parsed_new_process_id.clone(),
capabilities: requested_caps,
})?)
.inherit(true)
.send_and_await_response(5)??;
.send()?;
if let Some(to_grant) = &entry.grant_capabilities {
for value in to_grant {
match value {

View File

@ -1,7 +1,7 @@
[package]
name = "lib"
authors = ["KinodeDAO"]
version = "0.5.3"
version = "0.6.0"
edition = "2021"
description = "A general-purpose sovereign cloud computing platform"
homepage = "https://kinode.org"