mirror of
https://github.com/uqbar-dao/nectar.git
synced 2024-12-23 08:32:23 +03:00
rewrite app store to use its wit API
This commit is contained in:
parent
5dbf0745ca
commit
0dba348aca
30
Cargo.lock
generated
30
Cargo.lock
generated
@ -649,7 +649,7 @@ dependencies = [
|
|||||||
"alloy-sol-types 0.7.0",
|
"alloy-sol-types 0.7.0",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bincode",
|
"bincode",
|
||||||
"kinode_process_lib 0.8.0 (git+https://github.com/kinode-dao/process_lib?rev=09dc9f9)",
|
"kinode_process_lib 0.8.0 (git+https://github.com/kinode-dao/process_lib?rev=9998921)",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
@ -1935,7 +1935,7 @@ name = "download"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"kinode_process_lib 0.8.0 (git+https://github.com/kinode-dao/process_lib?rev=09dc9f9)",
|
"kinode_process_lib 0.8.0 (git+https://github.com/kinode-dao/process_lib?rev=9998921)",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"wit-bindgen",
|
"wit-bindgen",
|
||||||
@ -2887,7 +2887,7 @@ name = "install"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"kinode_process_lib 0.8.0 (git+https://github.com/kinode-dao/process_lib?rev=09dc9f9)",
|
"kinode_process_lib 0.8.0 (git+https://github.com/kinode-dao/process_lib?rev=9998921)",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"wit-bindgen",
|
"wit-bindgen",
|
||||||
@ -3217,6 +3217,28 @@ dependencies = [
|
|||||||
"wit-bindgen",
|
"wit-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "kinode_process_lib"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "git+https://github.com/kinode-dao/process_lib?rev=9998921#9998921364561368fdb22f5b2839c60e1bda87a1"
|
||||||
|
dependencies = [
|
||||||
|
"alloy-json-rpc 0.1.0 (git+https://github.com/alloy-rs/alloy.git?rev=cad7935)",
|
||||||
|
"alloy-primitives 0.7.0",
|
||||||
|
"alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy.git?rev=cad7935)",
|
||||||
|
"alloy-transport 0.1.0 (git+https://github.com/alloy-rs/alloy.git?rev=cad7935)",
|
||||||
|
"anyhow",
|
||||||
|
"bincode",
|
||||||
|
"http 1.1.0",
|
||||||
|
"mime_guess",
|
||||||
|
"rand 0.8.5",
|
||||||
|
"rmp-serde",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"thiserror",
|
||||||
|
"url",
|
||||||
|
"wit-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kit"
|
name = "kit"
|
||||||
version = "0.4.2"
|
version = "0.4.2"
|
||||||
@ -5913,7 +5935,7 @@ name = "uninstall"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"kinode_process_lib 0.8.0 (git+https://github.com/kinode-dao/process_lib?rev=09dc9f9)",
|
"kinode_process_lib 0.8.0 (git+https://github.com/kinode-dao/process_lib?rev=9998921)",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"wit-bindgen",
|
"wit-bindgen",
|
||||||
|
@ -3,10 +3,7 @@ interface main {
|
|||||||
// app store API as presented by main:app_store:sys-v0
|
// app store API as presented by main:app_store:sys-v0
|
||||||
//
|
//
|
||||||
|
|
||||||
record package-id {
|
use standard.{package-id};
|
||||||
package-name: string,
|
|
||||||
publisher-node: string,
|
|
||||||
}
|
|
||||||
|
|
||||||
record onchain-metadata {
|
record onchain-metadata {
|
||||||
name: option<string>,
|
name: option<string>,
|
@ -11,7 +11,7 @@ alloy-primitives = "0.7.0"
|
|||||||
alloy-sol-types = "0.7.0"
|
alloy-sol-types = "0.7.0"
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
bincode = "1.3.3"
|
bincode = "1.3.3"
|
||||||
kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "09dc9f9" }
|
kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "9998921" }
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
|
@ -1,169 +0,0 @@
|
|||||||
use kinode_process_lib::*;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
//
|
|
||||||
// app store API
|
|
||||||
//
|
|
||||||
|
|
||||||
/// Remote requests, those sent between instantiations of this process
|
|
||||||
/// on different nodes, take this form. Will add more here in the future
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
pub enum RemoteRequest {
|
|
||||||
/// Request a package from another node who we expect to
|
|
||||||
/// be mirroring it. If the remote node is mirroring the package,
|
|
||||||
/// they must respond with RemoteResponse::DownloadApproved,
|
|
||||||
/// at which point requester can expect an FTWorkerRequest::Receive.
|
|
||||||
Download {
|
|
||||||
package_id: PackageId,
|
|
||||||
desired_version_hash: Option<String>,
|
|
||||||
},
|
|
||||||
/// Request a package API from another node who we expect to
|
|
||||||
/// be mirroring it. If the remote node is mirroring the package,
|
|
||||||
/// they must respond with RemoteResponse::DownloadApproved,
|
|
||||||
/// at which point requester can expect an FTWorkerRequest::Receive.
|
|
||||||
DownloadApi {
|
|
||||||
package_id: PackageId,
|
|
||||||
desired_version_hash: Option<String>,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The response expected from sending a [`RemoteRequest`].
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
pub enum RemoteResponse {
|
|
||||||
DownloadApproved,
|
|
||||||
DownloadDenied(ReasonDenied),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
pub enum ReasonDenied {
|
|
||||||
NoPackage,
|
|
||||||
NotMirroring,
|
|
||||||
HashMismatch { requested: String, have: String },
|
|
||||||
FileNotFound,
|
|
||||||
WorkerSpawnFailed,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Local requests sent to the app store take this form.
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
pub enum LocalRequest {
|
|
||||||
/// Expects a zipped package as blob, and creates a new package from it.
|
|
||||||
///
|
|
||||||
/// If requested, will return a NewPackageResponse indicating success/failure.
|
|
||||||
/// This is used for locally installing a package.
|
|
||||||
NewPackage {
|
|
||||||
package: PackageId,
|
|
||||||
metadata: kernel_types::Erc721Metadata,
|
|
||||||
/// Sets whether we will mirror this package for others
|
|
||||||
mirror: bool,
|
|
||||||
},
|
|
||||||
/// Try to download a package from a specified node.
|
|
||||||
///
|
|
||||||
/// If requested, will return a DownloadResponse indicating success/failure.
|
|
||||||
/// No blob is expected.
|
|
||||||
Download {
|
|
||||||
package: PackageId,
|
|
||||||
download_from: NodeId,
|
|
||||||
/// Sets whether we will mirror this package for others
|
|
||||||
mirror: bool,
|
|
||||||
/// Sets whether we will try to automatically update this package
|
|
||||||
/// when a new version is posted to the listings contract
|
|
||||||
auto_update: bool,
|
|
||||||
/// The version hash we're looking for. If None, will download the latest.
|
|
||||||
desired_version_hash: Option<String>,
|
|
||||||
},
|
|
||||||
/// Select a downloaded package and install it. Will only succeed if the
|
|
||||||
/// package is currently in the filesystem. If the package has *already*
|
|
||||||
/// been installed, this will kill the running package and reset it with
|
|
||||||
/// what's on disk.
|
|
||||||
///
|
|
||||||
/// If requested, will return an InstallResponse indicating success/failure.
|
|
||||||
/// No blob is expected.
|
|
||||||
Install(PackageId),
|
|
||||||
/// Select an installed package and uninstall it.
|
|
||||||
/// This will kill the processes in the **manifest** of the package,
|
|
||||||
/// but not the processes that were spawned by those processes! Take
|
|
||||||
/// care to kill those processes yourself. This will also delete the drive
|
|
||||||
/// containing the source code for this package. This does not guarantee
|
|
||||||
/// that other data created by this package will be removed from places such
|
|
||||||
/// as the key-value store.
|
|
||||||
///
|
|
||||||
/// If requested, will return an UninstallResponse indicating success/failure.
|
|
||||||
/// No blob is expected.
|
|
||||||
Uninstall(PackageId),
|
|
||||||
/// Start mirroring a package. This will fail if the package has not been downloaded.
|
|
||||||
StartMirroring(PackageId),
|
|
||||||
/// Stop mirroring a package. This will fail if the package has not been downloaded.
|
|
||||||
StopMirroring(PackageId),
|
|
||||||
/// Turn on automatic updates to a package. This will fail if the package has not been downloaded.
|
|
||||||
StartAutoUpdate(PackageId),
|
|
||||||
/// Turn off automatic updates to a package. This will fail if the package has not been downloaded.
|
|
||||||
StopAutoUpdate(PackageId),
|
|
||||||
/// This is an expensive operation! Throw away our state and rebuild from scratch.
|
|
||||||
/// Re-index the locally downloaded/installed packages AND the onchain data.
|
|
||||||
RebuildIndex,
|
|
||||||
/// List all apps we have APIs for.
|
|
||||||
ListApis,
|
|
||||||
/// Return the given API, if we have it.
|
|
||||||
GetApi(PackageId),
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Local responses take this form.
|
|
||||||
/// The variant of `LocalResponse` given will match the `LocalRequest` it is
|
|
||||||
/// responding to.
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
pub enum LocalResponse {
|
|
||||||
NewPackageResponse(NewPackageResponse),
|
|
||||||
DownloadResponse(DownloadResponse),
|
|
||||||
InstallResponse(InstallResponse),
|
|
||||||
UninstallResponse(UninstallResponse),
|
|
||||||
MirrorResponse(MirrorResponse),
|
|
||||||
AutoUpdateResponse(AutoUpdateResponse),
|
|
||||||
RebuiltIndex,
|
|
||||||
ListApisResponse { apis: Vec<PackageId> },
|
|
||||||
GetApiResponse(GetApiResponse), // API in blob (or None)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO for all: expand these to elucidate why something failed
|
|
||||||
// these are locally-given responses to local requests
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
pub enum NewPackageResponse {
|
|
||||||
Success,
|
|
||||||
Failure,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
pub enum DownloadResponse {
|
|
||||||
Started,
|
|
||||||
Failure,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
pub enum InstallResponse {
|
|
||||||
Success,
|
|
||||||
Failure,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
pub enum UninstallResponse {
|
|
||||||
Success,
|
|
||||||
Failure,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
pub enum MirrorResponse {
|
|
||||||
Success,
|
|
||||||
Failure,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
pub enum AutoUpdateResponse {
|
|
||||||
Success,
|
|
||||||
Failure,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
pub enum GetApiResponse {
|
|
||||||
Success,
|
|
||||||
Failure,
|
|
||||||
}
|
|
@ -1,4 +1,5 @@
|
|||||||
use crate::{DownloadResponse, PackageListing, PackageState, RequestedPackage, State};
|
use crate::types::{PackageListing, PackageState, RequestedPackage, State};
|
||||||
|
use crate::DownloadResponse;
|
||||||
use kinode_process_lib::{
|
use kinode_process_lib::{
|
||||||
eth,
|
eth,
|
||||||
http::{send_response, IncomingHttpRequest, Method, StatusCode},
|
http::{send_response, IncomingHttpRequest, Method, StatusCode},
|
||||||
@ -223,7 +224,7 @@ fn serve_paths(
|
|||||||
None,
|
None,
|
||||||
format!("Downloading").into_bytes(),
|
format!("Downloading").into_bytes(),
|
||||||
)),
|
)),
|
||||||
DownloadResponse::Failure => Ok((
|
_ => Ok((
|
||||||
StatusCode::SERVICE_UNAVAILABLE,
|
StatusCode::SERVICE_UNAVAILABLE,
|
||||||
None,
|
None,
|
||||||
format!("Failed to download").into_bytes(),
|
format!("Failed to download").into_bytes(),
|
||||||
@ -319,7 +320,7 @@ fn serve_paths(
|
|||||||
None,
|
None,
|
||||||
format!("Downloading").into_bytes(),
|
format!("Downloading").into_bytes(),
|
||||||
)),
|
)),
|
||||||
DownloadResponse::Failure => Ok((
|
_ => Ok((
|
||||||
StatusCode::SERVICE_UNAVAILABLE,
|
StatusCode::SERVICE_UNAVAILABLE,
|
||||||
None,
|
None,
|
||||||
format!("Failed to download").into_bytes(),
|
format!("Failed to download").into_bytes(),
|
||||||
|
@ -1,23 +1,30 @@
|
|||||||
use kinode_process_lib::http::{
|
use crate::kinode::process::main::{
|
||||||
bind_http_path, bind_ws_path, send_ws_push, serve_ui, HttpServerRequest, WsMessageType,
|
ApisResponse, AutoUpdateResponse, DownloadRequest, DownloadResponse, GetApiResponse,
|
||||||
|
InstallResponse, LocalRequest, LocalResponse, MirrorResponse, NewPackageRequest,
|
||||||
|
NewPackageResponse, Reason, RebuildIndexResponse, RemoteDownloadRequest, RemoteRequest,
|
||||||
|
RemoteResponse, UninstallResponse,
|
||||||
};
|
};
|
||||||
use kinode_process_lib::kernel_types as kt;
|
use kinode_process_lib::kernel_types as kt;
|
||||||
use kinode_process_lib::*;
|
use kinode_process_lib::{
|
||||||
use kinode_process_lib::{call_init, println};
|
await_message, call_init, get_blob, get_capability, get_typed_state, println,
|
||||||
|
};
|
||||||
|
use kinode_process_lib::{
|
||||||
|
eth, http, vfs, Address, LazyLoadBlob, Message, NodeId, PackageId, ProcessId, Request, Response,
|
||||||
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
wit_bindgen::generate!({
|
wit_bindgen::generate!({
|
||||||
path: "target/wit",
|
path: "target/wit",
|
||||||
world: "process-v0",
|
generate_unused_types: true,
|
||||||
|
world: "app-store-sys-v0",
|
||||||
|
additional_derives: [PartialEq, serde::Deserialize, serde::Serialize],
|
||||||
});
|
});
|
||||||
|
|
||||||
mod api;
|
|
||||||
mod http_api;
|
mod http_api;
|
||||||
use api::*;
|
|
||||||
mod types;
|
mod types;
|
||||||
use types::*;
|
use types::{PackageState, RequestedPackage, State};
|
||||||
mod ft_worker_lib;
|
mod ft_worker_lib;
|
||||||
use ft_worker_lib::{
|
use ft_worker_lib::{
|
||||||
spawn_receive_transfer, spawn_transfer, FTWorkerCommand, FTWorkerResult, FileTransferContext,
|
spawn_receive_transfer, spawn_transfer, FTWorkerCommand, FTWorkerResult, FileTransferContext,
|
||||||
@ -70,7 +77,7 @@ pub enum Req {
|
|||||||
FTWorkerCommand(FTWorkerCommand),
|
FTWorkerCommand(FTWorkerCommand),
|
||||||
FTWorkerResult(FTWorkerResult),
|
FTWorkerResult(FTWorkerResult),
|
||||||
Eth(eth::EthSubResult),
|
Eth(eth::EthSubResult),
|
||||||
Http(HttpServerRequest),
|
Http(http::HttpServerRequest),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
@ -190,9 +197,9 @@ fn init(our: Address) {
|
|||||||
"/apps/:id/auto-update",
|
"/apps/:id/auto-update",
|
||||||
"/apps/rebuild-index",
|
"/apps/rebuild-index",
|
||||||
] {
|
] {
|
||||||
bind_http_path(path, true, false).expect("failed to bind http path");
|
http::bind_http_path(path, true, false).expect("failed to bind http path");
|
||||||
}
|
}
|
||||||
serve_ui(
|
http::serve_ui(
|
||||||
&our,
|
&our,
|
||||||
"ui",
|
"ui",
|
||||||
true,
|
true,
|
||||||
@ -201,7 +208,7 @@ fn init(our: Address) {
|
|||||||
)
|
)
|
||||||
.expect("failed to serve static UI");
|
.expect("failed to serve static UI");
|
||||||
|
|
||||||
bind_ws_path("/", true, true).expect("failed to bind ws path");
|
http::bind_ws_path("/", true, true).expect("failed to bind ws path");
|
||||||
|
|
||||||
// add ourselves to the homepage
|
// add ourselves to the homepage
|
||||||
Request::to(("our", "homepage", "homepage", "sys"))
|
Request::to(("our", "homepage", "homepage", "sys"))
|
||||||
@ -221,20 +228,17 @@ fn init(our: Address) {
|
|||||||
.send()
|
.send()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let mut state: State = match get_typed_state(|bytes| Ok(bincode::deserialize::<State>(bytes)?))
|
let mut state: State =
|
||||||
{
|
match get_typed_state(|bytes| Ok(serde_json::from_slice::<State>(bytes)?)) {
|
||||||
Some(state) => {
|
Some(state) => {
|
||||||
println!("loaded saved state");
|
println!("loaded saved state");
|
||||||
state
|
state
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
println!("failed to load state, initializing");
|
println!("failed to load state, initializing");
|
||||||
State::new(CONTRACT_ADDRESS.to_string()).unwrap()
|
State::new(CONTRACT_ADDRESS.to_string()).unwrap()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// // load in our saved state or initalize a new one if none exists
|
|
||||||
// let mut state = get_typed_state(|bytes| Ok(bincode::deserialize(bytes)?))
|
|
||||||
// .unwrap_or(State::new(CONTRACT_ADDRESS.to_string()).unwrap());
|
|
||||||
|
|
||||||
if state.contract_address != CONTRACT_ADDRESS {
|
if state.contract_address != CONTRACT_ADDRESS {
|
||||||
println!("warning: contract address mismatch--overwriting saved state");
|
println!("warning: contract address mismatch--overwriting saved state");
|
||||||
@ -283,9 +287,9 @@ fn init(our: Address) {
|
|||||||
&message,
|
&message,
|
||||||
) {
|
) {
|
||||||
println!("error handling message: {:?}", e);
|
println!("error handling message: {:?}", e);
|
||||||
send_ws_push(
|
http::send_ws_push(
|
||||||
channel_id,
|
channel_id,
|
||||||
WsMessageType::Text,
|
http::WsMessageType::Text,
|
||||||
LazyLoadBlob {
|
LazyLoadBlob {
|
||||||
mime: Some("application/json".to_string()),
|
mime: Some("application/json".to_string()),
|
||||||
bytes: serde_json::json!({
|
bytes: serde_json::json!({
|
||||||
@ -328,7 +332,7 @@ fn handle_message(
|
|||||||
}
|
}
|
||||||
let (body, blob) = handle_local_request(
|
let (body, blob) = handle_local_request(
|
||||||
&our,
|
&our,
|
||||||
&local_request,
|
local_request,
|
||||||
state,
|
state,
|
||||||
eth_provider,
|
eth_provider,
|
||||||
requested_apis,
|
requested_apis,
|
||||||
@ -345,7 +349,7 @@ fn handle_message(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Req::RemoteRequest(remote_request) => {
|
Req::RemoteRequest(remote_request) => {
|
||||||
let resp = handle_remote_request(&our, &source, &remote_request, state);
|
let resp = handle_remote_request(&our, &source, remote_request, state);
|
||||||
if expects_response.is_some() {
|
if expects_response.is_some() {
|
||||||
Response::new().body(serde_json::to_vec(&resp)?).send()?;
|
Response::new().body(serde_json::to_vec(&resp)?).send()?;
|
||||||
}
|
}
|
||||||
@ -384,7 +388,7 @@ fn handle_message(
|
|||||||
{
|
{
|
||||||
return Err(anyhow::anyhow!("http_server from non-local node"));
|
return Err(anyhow::anyhow!("http_server from non-local node"));
|
||||||
}
|
}
|
||||||
if let HttpServerRequest::Http(req) = incoming {
|
if let http::HttpServerRequest::Http(req) = incoming {
|
||||||
http_api::handle_http_request(
|
http_api::handle_http_request(
|
||||||
our,
|
our,
|
||||||
state,
|
state,
|
||||||
@ -411,32 +415,24 @@ fn handle_message(
|
|||||||
fn handle_remote_request(
|
fn handle_remote_request(
|
||||||
our: &Address,
|
our: &Address,
|
||||||
source: &Address,
|
source: &Address,
|
||||||
request: &RemoteRequest,
|
request: RemoteRequest,
|
||||||
state: &mut State,
|
state: &mut State,
|
||||||
) -> Resp {
|
) -> Resp {
|
||||||
match request {
|
match request {
|
||||||
RemoteRequest::Download {
|
RemoteRequest::Download(RemoteDownloadRequest {
|
||||||
package_id,
|
package_id,
|
||||||
desired_version_hash,
|
desired_version_hash,
|
||||||
} => {
|
}) => {
|
||||||
let Some(package_state) = state.get_downloaded_package(package_id) else {
|
let package_id = package_id.to_process_lib();
|
||||||
return Resp::RemoteResponse(RemoteResponse::DownloadDenied(
|
let Some(package_state) = state.get_downloaded_package(&package_id) else {
|
||||||
ReasonDenied::NoPackage,
|
return Resp::RemoteResponse(RemoteResponse::Denied(Reason::NoPackage));
|
||||||
));
|
|
||||||
};
|
};
|
||||||
if !package_state.mirroring {
|
if !package_state.mirroring {
|
||||||
return Resp::RemoteResponse(RemoteResponse::DownloadDenied(
|
return Resp::RemoteResponse(RemoteResponse::Denied(Reason::NotMirroring));
|
||||||
ReasonDenied::NotMirroring,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
if let Some(hash) = desired_version_hash {
|
if let Some(hash) = desired_version_hash {
|
||||||
if &package_state.our_version != hash {
|
if package_state.our_version != hash {
|
||||||
return Resp::RemoteResponse(RemoteResponse::DownloadDenied(
|
return Resp::RemoteResponse(RemoteResponse::Denied(Reason::HashMismatch));
|
||||||
ReasonDenied::HashMismatch {
|
|
||||||
requested: hash.clone(),
|
|
||||||
have: package_state.our_version.clone(),
|
|
||||||
},
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let file_name = format!("/{}.zip", package_id);
|
let file_name = format!("/{}.zip", package_id);
|
||||||
@ -452,40 +448,28 @@ fn handle_remote_request(
|
|||||||
)
|
)
|
||||||
.send_and_await_response(5)
|
.send_and_await_response(5)
|
||||||
else {
|
else {
|
||||||
return Resp::RemoteResponse(RemoteResponse::DownloadDenied(
|
return Resp::RemoteResponse(RemoteResponse::Denied(Reason::NoPackage));
|
||||||
ReasonDenied::FileNotFound,
|
|
||||||
));
|
|
||||||
};
|
};
|
||||||
// transfer will *inherit* the blob bytes we receive from VFS
|
// transfer will *inherit* the blob bytes we receive from VFS
|
||||||
match spawn_transfer(&our, &file_name, None, 60, &source) {
|
match spawn_transfer(&our, &file_name, None, 60, &source) {
|
||||||
Ok(()) => Resp::RemoteResponse(RemoteResponse::DownloadApproved),
|
Ok(()) => Resp::RemoteResponse(RemoteResponse::Approved),
|
||||||
Err(_e) => Resp::RemoteResponse(RemoteResponse::DownloadDenied(
|
Err(_e) => Resp::RemoteResponse(RemoteResponse::Denied(Reason::NoPackage)),
|
||||||
ReasonDenied::WorkerSpawnFailed,
|
|
||||||
)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RemoteRequest::DownloadApi {
|
RemoteRequest::DownloadApi(RemoteDownloadRequest {
|
||||||
package_id,
|
package_id,
|
||||||
desired_version_hash,
|
desired_version_hash,
|
||||||
} => {
|
}) => {
|
||||||
let Some(package_state) = state.get_downloaded_package(package_id) else {
|
let package_id = package_id.to_process_lib();
|
||||||
return Resp::RemoteResponse(RemoteResponse::DownloadDenied(
|
let Some(package_state) = state.get_downloaded_package(&package_id) else {
|
||||||
ReasonDenied::NoPackage,
|
return Resp::RemoteResponse(RemoteResponse::Denied(Reason::NoPackage));
|
||||||
));
|
|
||||||
};
|
};
|
||||||
if !package_state.mirroring {
|
if !package_state.mirroring {
|
||||||
return Resp::RemoteResponse(RemoteResponse::DownloadDenied(
|
return Resp::RemoteResponse(RemoteResponse::Denied(Reason::NotMirroring));
|
||||||
ReasonDenied::NotMirroring,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
if let Some(desired_version_hash) = desired_version_hash {
|
if let Some(desired_version_hash) = desired_version_hash {
|
||||||
if &package_state.our_version != desired_version_hash {
|
if package_state.our_version != desired_version_hash {
|
||||||
return Resp::RemoteResponse(RemoteResponse::DownloadDenied(
|
return Resp::RemoteResponse(RemoteResponse::Denied(Reason::HashMismatch));
|
||||||
ReasonDenied::HashMismatch {
|
|
||||||
requested: desired_version_hash.clone(),
|
|
||||||
have: package_state.our_version.clone(),
|
|
||||||
},
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let file_name = format!("/{}-api-v0.zip", package_id); // TODO: actual version
|
let file_name = format!("/{}-api-v0.zip", package_id); // TODO: actual version
|
||||||
@ -501,16 +485,12 @@ fn handle_remote_request(
|
|||||||
)
|
)
|
||||||
.send_and_await_response(5)
|
.send_and_await_response(5)
|
||||||
else {
|
else {
|
||||||
return Resp::RemoteResponse(RemoteResponse::DownloadDenied(
|
return Resp::RemoteResponse(RemoteResponse::Denied(Reason::NoPackage));
|
||||||
ReasonDenied::FileNotFound,
|
|
||||||
));
|
|
||||||
};
|
};
|
||||||
// transfer will *inherit* the blob bytes we receive from VFS
|
// transfer will *inherit* the blob bytes we receive from VFS
|
||||||
match spawn_transfer(&our, &file_name, None, 60, &source) {
|
match spawn_transfer(&our, &file_name, None, 60, &source) {
|
||||||
Ok(()) => Resp::RemoteResponse(RemoteResponse::DownloadApproved),
|
Ok(()) => Resp::RemoteResponse(RemoteResponse::Approved),
|
||||||
Err(_e) => Resp::RemoteResponse(RemoteResponse::DownloadDenied(
|
Err(_e) => Resp::RemoteResponse(RemoteResponse::Denied(Reason::NoPackage)),
|
||||||
ReasonDenied::WorkerSpawnFailed,
|
|
||||||
)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -519,26 +499,27 @@ fn handle_remote_request(
|
|||||||
/// only `our.node` can call this
|
/// only `our.node` can call this
|
||||||
fn handle_local_request(
|
fn handle_local_request(
|
||||||
our: &Address,
|
our: &Address,
|
||||||
request: &LocalRequest,
|
request: LocalRequest,
|
||||||
state: &mut State,
|
state: &mut State,
|
||||||
eth_provider: ð::Provider,
|
eth_provider: ð::Provider,
|
||||||
requested_apis: &mut HashMap<PackageId, RequestedPackage>,
|
requested_apis: &mut HashMap<PackageId, RequestedPackage>,
|
||||||
requested_packages: &mut HashMap<PackageId, RequestedPackage>,
|
requested_packages: &mut HashMap<PackageId, RequestedPackage>,
|
||||||
) -> (LocalResponse, Option<LazyLoadBlob>) {
|
) -> (LocalResponse, Option<LazyLoadBlob>) {
|
||||||
match request {
|
match request {
|
||||||
LocalRequest::NewPackage {
|
LocalRequest::NewPackage(NewPackageRequest {
|
||||||
package,
|
package_id,
|
||||||
metadata,
|
metadata,
|
||||||
mirror,
|
mirror,
|
||||||
} => {
|
}) => {
|
||||||
|
let package_id = package_id.to_process_lib();
|
||||||
let Some(blob) = get_blob() else {
|
let Some(blob) = get_blob() else {
|
||||||
return (
|
return (
|
||||||
LocalResponse::NewPackageResponse(NewPackageResponse::Failure),
|
LocalResponse::NewPackageResponse(NewPackageResponse::NoBlob),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
// set the version hash for this new local package
|
// set the version hash for this new local package
|
||||||
let our_version = generate_version_hash(&blob.bytes);
|
let our_version = types::generate_version_hash(&blob.bytes);
|
||||||
|
|
||||||
let package_state = PackageState {
|
let package_state = PackageState {
|
||||||
mirrored_from: Some(our.node.clone()),
|
mirrored_from: Some(our.node.clone()),
|
||||||
@ -547,19 +528,19 @@ fn handle_local_request(
|
|||||||
verified: true, // side loaded apps are implicitly verified because there is no "source" to verify against
|
verified: true, // side loaded apps are implicitly verified because there is no "source" to verify against
|
||||||
caps_approved: true, // TODO see if we want to auto-approve local installs
|
caps_approved: true, // TODO see if we want to auto-approve local installs
|
||||||
manifest_hash: None, // generated in the add fn
|
manifest_hash: None, // generated in the add fn
|
||||||
mirroring: *mirror,
|
mirroring: mirror,
|
||||||
auto_update: false, // can't auto-update a local package
|
auto_update: false, // can't auto-update a local package
|
||||||
metadata: Some(metadata.clone()),
|
metadata: Some(metadata.to_erc721_metadata()),
|
||||||
};
|
};
|
||||||
let Ok(()) = state.add_downloaded_package(package, package_state, Some(blob.bytes))
|
let Ok(()) = state.add_downloaded_package(&package_id, package_state, Some(blob.bytes))
|
||||||
else {
|
else {
|
||||||
return (
|
return (
|
||||||
LocalResponse::NewPackageResponse(NewPackageResponse::Failure),
|
LocalResponse::NewPackageResponse(NewPackageResponse::InstallFailed),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
let drive_path = format!("/{package}/pkg");
|
let drive_path = format!("/{package_id}/pkg");
|
||||||
let result = Request::new()
|
let result = Request::new()
|
||||||
.target(("our", "vfs", "distro", "sys"))
|
.target(("our", "vfs", "distro", "sys"))
|
||||||
.body(
|
.body(
|
||||||
@ -571,7 +552,7 @@ fn handle_local_request(
|
|||||||
)
|
)
|
||||||
.send_and_await_response(5);
|
.send_and_await_response(5);
|
||||||
if let Ok(Ok(_)) = result {
|
if let Ok(Ok(_)) = result {
|
||||||
state.downloaded_apis.insert(package.to_owned());
|
state.downloaded_apis.insert(package_id.to_owned());
|
||||||
};
|
};
|
||||||
|
|
||||||
(
|
(
|
||||||
@ -579,61 +560,61 @@ fn handle_local_request(
|
|||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
LocalRequest::Download {
|
LocalRequest::Download(DownloadRequest {
|
||||||
package: package_id,
|
package_id,
|
||||||
download_from,
|
download_from,
|
||||||
mirror,
|
mirror,
|
||||||
auto_update,
|
auto_update,
|
||||||
desired_version_hash,
|
desired_version_hash,
|
||||||
} => (
|
}) => (
|
||||||
LocalResponse::DownloadResponse(start_download(
|
LocalResponse::DownloadResponse(start_download(
|
||||||
our,
|
our,
|
||||||
requested_packages,
|
requested_packages,
|
||||||
package_id,
|
&package_id.to_process_lib(),
|
||||||
download_from,
|
&download_from,
|
||||||
*mirror,
|
mirror,
|
||||||
*auto_update,
|
auto_update,
|
||||||
desired_version_hash,
|
&desired_version_hash,
|
||||||
)),
|
)),
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
LocalRequest::Install(package) => (
|
LocalRequest::Install(package_id) => (
|
||||||
match handle_install(our, state, package) {
|
match handle_install(our, state, &package_id.to_process_lib()) {
|
||||||
Ok(()) => LocalResponse::InstallResponse(InstallResponse::Success),
|
Ok(()) => LocalResponse::InstallResponse(InstallResponse::Success),
|
||||||
Err(_) => LocalResponse::InstallResponse(InstallResponse::Failure),
|
Err(_) => LocalResponse::InstallResponse(InstallResponse::Failure),
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
LocalRequest::Uninstall(package) => (
|
LocalRequest::Uninstall(package_id) => (
|
||||||
match state.uninstall(package) {
|
match state.uninstall(&package_id.to_process_lib()) {
|
||||||
Ok(()) => LocalResponse::UninstallResponse(UninstallResponse::Success),
|
Ok(()) => LocalResponse::UninstallResponse(UninstallResponse::Success),
|
||||||
Err(_) => LocalResponse::UninstallResponse(UninstallResponse::Failure),
|
Err(_) => LocalResponse::UninstallResponse(UninstallResponse::Failure),
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
LocalRequest::StartMirroring(package) => (
|
LocalRequest::StartMirroring(package_id) => (
|
||||||
match state.start_mirroring(package) {
|
match state.start_mirroring(&package_id.to_process_lib()) {
|
||||||
true => LocalResponse::MirrorResponse(MirrorResponse::Success),
|
true => LocalResponse::MirrorResponse(MirrorResponse::Success),
|
||||||
false => LocalResponse::MirrorResponse(MirrorResponse::Failure),
|
false => LocalResponse::MirrorResponse(MirrorResponse::Failure),
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
LocalRequest::StopMirroring(package) => (
|
LocalRequest::StopMirroring(package_id) => (
|
||||||
match state.stop_mirroring(package) {
|
match state.stop_mirroring(&package_id.to_process_lib()) {
|
||||||
true => LocalResponse::MirrorResponse(MirrorResponse::Success),
|
true => LocalResponse::MirrorResponse(MirrorResponse::Success),
|
||||||
false => LocalResponse::MirrorResponse(MirrorResponse::Failure),
|
false => LocalResponse::MirrorResponse(MirrorResponse::Failure),
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
LocalRequest::StartAutoUpdate(package) => (
|
LocalRequest::StartAutoUpdate(package_id) => (
|
||||||
match state.start_auto_update(package) {
|
match state.start_auto_update(&package_id.to_process_lib()) {
|
||||||
true => LocalResponse::AutoUpdateResponse(AutoUpdateResponse::Success),
|
true => LocalResponse::AutoUpdateResponse(AutoUpdateResponse::Success),
|
||||||
false => LocalResponse::AutoUpdateResponse(AutoUpdateResponse::Failure),
|
false => LocalResponse::AutoUpdateResponse(AutoUpdateResponse::Failure),
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
LocalRequest::StopAutoUpdate(package) => (
|
LocalRequest::StopAutoUpdate(package_id) => (
|
||||||
match state.stop_auto_update(package) {
|
match state.stop_auto_update(&package_id.to_process_lib()) {
|
||||||
true => LocalResponse::AutoUpdateResponse(AutoUpdateResponse::Success),
|
true => LocalResponse::AutoUpdateResponse(AutoUpdateResponse::Success),
|
||||||
false => LocalResponse::AutoUpdateResponse(AutoUpdateResponse::Failure),
|
false => LocalResponse::AutoUpdateResponse(AutoUpdateResponse::Failure),
|
||||||
},
|
},
|
||||||
@ -643,8 +624,8 @@ fn handle_local_request(
|
|||||||
rebuild_index(our, state, eth_provider, requested_apis),
|
rebuild_index(our, state, eth_provider, requested_apis),
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
LocalRequest::ListApis => (list_apis(state), None),
|
LocalRequest::Apis => (list_apis(state), None),
|
||||||
LocalRequest::GetApi(ref package_id) => get_api(package_id, state),
|
LocalRequest::GetApi(package_id) => get_api(&package_id.to_process_lib(), state),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -679,9 +660,14 @@ pub fn get_api(package_id: &PackageId, state: &mut State) -> (LocalResponse, Opt
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn list_apis(state: &mut State) -> LocalResponse {
|
pub fn list_apis(state: &mut State) -> LocalResponse {
|
||||||
LocalResponse::ListApisResponse {
|
LocalResponse::ApisResponse(ApisResponse {
|
||||||
apis: state.downloaded_apis.iter().cloned().collect(),
|
apis: state
|
||||||
}
|
.downloaded_apis
|
||||||
|
.clone()
|
||||||
|
.into_iter()
|
||||||
|
.map(|id| crate::kinode::process::main::PackageId::from_process_lib(id))
|
||||||
|
.collect(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rebuild_index(
|
pub fn rebuild_index(
|
||||||
@ -707,7 +693,7 @@ pub fn rebuild_index(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalResponse::RebuiltIndex
|
LocalResponse::RebuildIndexResponse(RebuildIndexResponse::Success)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start_api_download(
|
pub fn start_api_download(
|
||||||
@ -720,16 +706,18 @@ pub fn start_api_download(
|
|||||||
match Request::to((download_from.as_str(), our.process.clone()))
|
match Request::to((download_from.as_str(), our.process.clone()))
|
||||||
.inherit(true)
|
.inherit(true)
|
||||||
.body(
|
.body(
|
||||||
serde_json::to_vec(&RemoteRequest::DownloadApi {
|
serde_json::to_vec(&RemoteRequest::DownloadApi(RemoteDownloadRequest {
|
||||||
package_id: package_id.clone(),
|
package_id: crate::kinode::process::main::PackageId::from_process_lib(
|
||||||
|
package_id.clone(),
|
||||||
|
),
|
||||||
desired_version_hash: desired_version_hash.map(|s| s.to_string()),
|
desired_version_hash: desired_version_hash.map(|s| s.to_string()),
|
||||||
})
|
}))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
.send_and_await_response(5)
|
.send_and_await_response(5)
|
||||||
{
|
{
|
||||||
Ok(Ok(Message::Response { body, .. })) => match serde_json::from_slice::<Resp>(&body) {
|
Ok(Ok(Message::Response { body, .. })) => match serde_json::from_slice::<Resp>(&body) {
|
||||||
Ok(Resp::RemoteResponse(RemoteResponse::DownloadApproved)) => {
|
Ok(Resp::RemoteResponse(RemoteResponse::Approved)) => {
|
||||||
requested_apis.insert(
|
requested_apis.insert(
|
||||||
package_id,
|
package_id,
|
||||||
RequestedPackage {
|
RequestedPackage {
|
||||||
@ -741,9 +729,9 @@ pub fn start_api_download(
|
|||||||
);
|
);
|
||||||
DownloadResponse::Started
|
DownloadResponse::Started
|
||||||
}
|
}
|
||||||
_ => DownloadResponse::Failure,
|
_ => DownloadResponse::BadResponse,
|
||||||
},
|
},
|
||||||
_ => DownloadResponse::Failure,
|
_ => DownloadResponse::BadResponse,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -759,16 +747,18 @@ pub fn start_download(
|
|||||||
match Request::to((download_from.as_str(), our.process.clone()))
|
match Request::to((download_from.as_str(), our.process.clone()))
|
||||||
.inherit(true)
|
.inherit(true)
|
||||||
.body(
|
.body(
|
||||||
serde_json::to_vec(&RemoteRequest::Download {
|
serde_json::to_vec(&RemoteRequest::Download(RemoteDownloadRequest {
|
||||||
package_id: package_id.clone(),
|
package_id: crate::kinode::process::main::PackageId::from_process_lib(
|
||||||
|
package_id.clone(),
|
||||||
|
),
|
||||||
desired_version_hash: desired_version_hash.clone(),
|
desired_version_hash: desired_version_hash.clone(),
|
||||||
})
|
}))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
.send_and_await_response(5)
|
.send_and_await_response(5)
|
||||||
{
|
{
|
||||||
Ok(Ok(Message::Response { body, .. })) => match serde_json::from_slice::<Resp>(&body) {
|
Ok(Ok(Message::Response { body, .. })) => match serde_json::from_slice::<Resp>(&body) {
|
||||||
Ok(Resp::RemoteResponse(RemoteResponse::DownloadApproved)) => {
|
Ok(Resp::RemoteResponse(RemoteResponse::Approved)) => {
|
||||||
requested_packages.insert(
|
requested_packages.insert(
|
||||||
package_id.clone(),
|
package_id.clone(),
|
||||||
RequestedPackage {
|
RequestedPackage {
|
||||||
@ -780,9 +770,9 @@ pub fn start_download(
|
|||||||
);
|
);
|
||||||
DownloadResponse::Started
|
DownloadResponse::Started
|
||||||
}
|
}
|
||||||
_ => DownloadResponse::Failure,
|
_ => DownloadResponse::BadResponse,
|
||||||
},
|
},
|
||||||
_ => DownloadResponse::Failure,
|
_ => DownloadResponse::BadResponse,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -834,7 +824,7 @@ fn handle_receive_download_api(
|
|||||||
};
|
};
|
||||||
// check the version hash for this download against requested!!
|
// check the version hash for this download against requested!!
|
||||||
// for now we can reject if it's not latest.
|
// for now we can reject if it's not latest.
|
||||||
let download_hash = generate_version_hash(&blob.bytes);
|
let download_hash = types::generate_version_hash(&blob.bytes);
|
||||||
let mut verified = false;
|
let mut verified = false;
|
||||||
// TODO: require api_hash
|
// TODO: require api_hash
|
||||||
if let Some(hash) = requested_package.desired_version_hash {
|
if let Some(hash) = requested_package.desired_version_hash {
|
||||||
@ -874,7 +864,7 @@ fn handle_receive_download_package(
|
|||||||
};
|
};
|
||||||
// check the version hash for this download against requested!!
|
// check the version hash for this download against requested!!
|
||||||
// for now we can reject if it's not latest.
|
// for now we can reject if it's not latest.
|
||||||
let download_hash = generate_version_hash(&blob.bytes);
|
let download_hash = types::generate_version_hash(&blob.bytes);
|
||||||
let mut verified = false;
|
let mut verified = false;
|
||||||
match requested_package.desired_version_hash {
|
match requested_package.desired_version_hash {
|
||||||
Some(hash) => {
|
Some(hash) => {
|
||||||
@ -907,13 +897,17 @@ fn handle_receive_download_package(
|
|||||||
let Some(latest_hash) = metadata
|
let Some(latest_hash) = metadata
|
||||||
.properties
|
.properties
|
||||||
.code_hashes
|
.code_hashes
|
||||||
|
.clone()
|
||||||
|
.into_iter()
|
||||||
|
.collect::<HashMap<_, _>>()
|
||||||
.get(&metadata.properties.current_version)
|
.get(&metadata.properties.current_version)
|
||||||
|
.cloned()
|
||||||
else {
|
else {
|
||||||
return Err(anyhow::anyhow!(
|
return Err(anyhow::anyhow!(
|
||||||
"downloaded package has no versions in manager--rejecting download!"
|
"downloaded package has no versions in manager--rejecting download!"
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
if &download_hash != latest_hash {
|
if download_hash != latest_hash {
|
||||||
if latest_hash.is_empty() {
|
if latest_hash.is_empty() {
|
||||||
println!(
|
println!(
|
||||||
"\x1b[33mwarning: downloaded package has no version hashes--cannot verify code integrity, proceeding anyways\x1b[0m"
|
"\x1b[33mwarning: downloaded package has no version hashes--cannot verify code integrity, proceeding anyways\x1b[0m"
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
use crate::{start_api_download, DownloadResponse, LocalRequest};
|
use crate::kinode::process::main::{DownloadRequest, LocalRequest, OnchainMetadata};
|
||||||
use alloy_sol_types::{sol, SolEvent};
|
use alloy_sol_types::{sol, SolEvent};
|
||||||
use kinode_process_lib::eth::Log;
|
use kinode_process_lib::{
|
||||||
use kinode_process_lib::kernel_types as kt;
|
eth::Log, get_blob, http, kernel_types as kt, net, println, vfs, Address, LazyLoadBlob,
|
||||||
use kinode_process_lib::{println, *};
|
Message, NodeId, PackageId, ProcessId, Request,
|
||||||
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
@ -37,6 +38,49 @@ pub enum IndexerRequests {
|
|||||||
NodeInfo { name: String, block: u64 },
|
NodeInfo { name: String, block: u64 },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// quite annoyingly, we must convert from our gen'd version of PackageId
|
||||||
|
// to the process_lib's gen'd version. this is in order to access custom
|
||||||
|
// Impls that we want to use
|
||||||
|
impl crate::kinode::process::main::PackageId {
|
||||||
|
pub fn to_process_lib(self) -> PackageId {
|
||||||
|
PackageId {
|
||||||
|
package_name: self.package_name,
|
||||||
|
publisher_node: self.publisher_node,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn from_process_lib(package_id: PackageId) -> Self {
|
||||||
|
Self {
|
||||||
|
package_name: package_id.package_name,
|
||||||
|
publisher_node: package_id.publisher_node,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// less annoying but still bad
|
||||||
|
impl OnchainMetadata {
|
||||||
|
pub fn to_erc721_metadata(self) -> kt::Erc721Metadata {
|
||||||
|
use kt::Erc721Properties;
|
||||||
|
kt::Erc721Metadata {
|
||||||
|
name: self.name,
|
||||||
|
description: self.description,
|
||||||
|
image: self.image,
|
||||||
|
external_url: self.external_url,
|
||||||
|
animation_url: self.animation_url,
|
||||||
|
properties: Erc721Properties {
|
||||||
|
package_name: self.properties.package_name,
|
||||||
|
publisher: self.properties.publisher,
|
||||||
|
current_version: self.properties.current_version,
|
||||||
|
mirrors: self.properties.mirrors,
|
||||||
|
code_hashes: self.properties.code_hashes.into_iter().collect(),
|
||||||
|
license: self.properties.license,
|
||||||
|
screenshots: self.properties.screenshots,
|
||||||
|
wit_version: self.properties.wit_version,
|
||||||
|
dependencies: self.properties.dependencies,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// app store types
|
// app store types
|
||||||
//
|
//
|
||||||
@ -113,7 +157,7 @@ impl State {
|
|||||||
/// To create a new state, we populate the downloaded_packages map
|
/// To create a new state, we populate the downloaded_packages map
|
||||||
/// with all packages parseable from our filesystem.
|
/// with all packages parseable from our filesystem.
|
||||||
pub fn new(contract_address: String) -> anyhow::Result<Self> {
|
pub fn new(contract_address: String) -> anyhow::Result<Self> {
|
||||||
crate::print_to_terminal(1, "producing new state");
|
kinode_process_lib::print_to_terminal(1, "producing new state");
|
||||||
let mut state = State {
|
let mut state = State {
|
||||||
contract_address,
|
contract_address,
|
||||||
last_saved_block: crate::CONTRACT_FIRST_BLOCK,
|
last_saved_block: crate::CONTRACT_FIRST_BLOCK,
|
||||||
@ -196,7 +240,7 @@ impl State {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
self.downloaded_apis.insert(package_id.to_owned());
|
self.downloaded_apis.insert(package_id.to_owned());
|
||||||
crate::set_state(&bincode::serialize(self)?);
|
kinode_process_lib::set_state(&serde_json::to_vec(self)?);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,7 +302,7 @@ impl State {
|
|||||||
}
|
}
|
||||||
self.downloaded_packages
|
self.downloaded_packages
|
||||||
.insert(package_id.to_owned(), package_state);
|
.insert(package_id.to_owned(), package_state);
|
||||||
crate::set_state(&bincode::serialize(self)?);
|
kinode_process_lib::set_state(&serde_json::to_vec(self)?);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,7 +320,7 @@ impl State {
|
|||||||
true
|
true
|
||||||
})
|
})
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
crate::set_state(&bincode::serialize(self).unwrap());
|
kinode_process_lib::set_state(&serde_json::to_vec(self).unwrap());
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -416,7 +460,7 @@ impl State {
|
|||||||
|
|
||||||
// finally, remove from downloaded packages
|
// finally, remove from downloaded packages
|
||||||
self.downloaded_packages.remove(package_id);
|
self.downloaded_packages.remove(package_id);
|
||||||
crate::set_state(&bincode::serialize(self)?);
|
kinode_process_lib::set_state(&serde_json::to_vec(self)?);
|
||||||
|
|
||||||
println!("uninstalled {package_id}");
|
println!("uninstalled {package_id}");
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -447,7 +491,7 @@ impl State {
|
|||||||
let package_hash = package_hash.to_string();
|
let package_hash = package_hash.to_string();
|
||||||
let metadata_hash = metadata_hash.to_string();
|
let metadata_hash = metadata_hash.to_string();
|
||||||
|
|
||||||
crate::print_to_terminal(
|
kinode_process_lib::print_to_terminal(
|
||||||
1,
|
1,
|
||||||
&format!(
|
&format!(
|
||||||
"app registered with package_name {}, metadata_url {}, metadata_hash {}",
|
"app registered with package_name {}, metadata_url {}, metadata_hash {}",
|
||||||
@ -529,7 +573,10 @@ impl State {
|
|||||||
Some(metadata)
|
Some(metadata)
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
crate::print_to_terminal(1, &format!("failed to fetch metadata: {e:?}"));
|
kinode_process_lib::print_to_terminal(
|
||||||
|
1,
|
||||||
|
&format!("failed to fetch metadata: {e:?}"),
|
||||||
|
);
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -545,18 +592,22 @@ impl State {
|
|||||||
if let Some(package_state) = self.downloaded_packages.get(&package_id) {
|
if let Some(package_state) = self.downloaded_packages.get(&package_id) {
|
||||||
if package_state.auto_update {
|
if package_state.auto_update {
|
||||||
if let Some(mirrored_from) = &package_state.mirrored_from {
|
if let Some(mirrored_from) = &package_state.mirrored_from {
|
||||||
crate::print_to_terminal(
|
kinode_process_lib::print_to_terminal(
|
||||||
1,
|
1,
|
||||||
&format!("auto-updating package {package_id} from {mirrored_from}"),
|
&format!("auto-updating package {package_id} from {mirrored_from}"),
|
||||||
);
|
);
|
||||||
Request::to(our)
|
Request::to(our)
|
||||||
.body(serde_json::to_vec(&LocalRequest::Download {
|
.body(serde_json::to_vec(&LocalRequest::Download(
|
||||||
package: package_id,
|
DownloadRequest {
|
||||||
download_from: mirrored_from.clone(),
|
package_id: crate::kinode::process::main::PackageId::from_process_lib(
|
||||||
mirror: package_state.mirroring,
|
package_id,
|
||||||
auto_update: package_state.auto_update,
|
),
|
||||||
desired_version_hash: None,
|
download_from: mirrored_from.clone(),
|
||||||
})?)
|
mirror: package_state.mirroring,
|
||||||
|
auto_update: package_state.auto_update,
|
||||||
|
desired_version_hash: None,
|
||||||
|
},
|
||||||
|
))?)
|
||||||
.send()?;
|
.send()?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -595,7 +646,7 @@ impl State {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
self.last_saved_block = block_number;
|
self.last_saved_block = block_number;
|
||||||
crate::set_state(&bincode::serialize(self)?);
|
kinode_process_lib::set_state(&serde_json::to_vec(self)?);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ simulation-mode = []
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "09dc9f9" }
|
kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "9998921" }
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
wit-bindgen = "0.24.0"
|
wit-bindgen = "0.24.0"
|
||||||
|
@ -1 +0,0 @@
|
|||||||
../../app_store/src/api.rs
|
|
@ -1,13 +1,14 @@
|
|||||||
|
use crate::kinode::process::main::{DownloadResponse, LocalRequest, LocalResponse};
|
||||||
|
use kinode::process::main::DownloadRequest;
|
||||||
use kinode_process_lib::{
|
use kinode_process_lib::{
|
||||||
await_next_message_body, call_init, println, Address, Message, NodeId, PackageId, Request,
|
await_next_message_body, call_init, println, Address, Message, NodeId, PackageId, Request,
|
||||||
};
|
};
|
||||||
|
|
||||||
mod api;
|
|
||||||
use api::*;
|
|
||||||
|
|
||||||
wit_bindgen::generate!({
|
wit_bindgen::generate!({
|
||||||
path: "target/wit",
|
path: "target/wit",
|
||||||
world: "process-v0",
|
generate_unused_types: true,
|
||||||
|
world: "app-store-sys-v0",
|
||||||
|
additional_derives: [PartialEq, serde::Deserialize, serde::Serialize],
|
||||||
});
|
});
|
||||||
|
|
||||||
call_init!(init);
|
call_init!(init);
|
||||||
@ -36,13 +37,16 @@ fn init(our: Address) {
|
|||||||
let Ok(Ok(Message::Response { body, .. })) =
|
let Ok(Ok(Message::Response { body, .. })) =
|
||||||
Request::to((our.node(), ("main", "app_store", "sys")))
|
Request::to((our.node(), ("main", "app_store", "sys")))
|
||||||
.body(
|
.body(
|
||||||
serde_json::to_vec(&LocalRequest::Download {
|
serde_json::to_vec(&LocalRequest::Download(DownloadRequest {
|
||||||
package: package_id.clone(),
|
package_id: crate::kinode::process::main::PackageId {
|
||||||
|
package_name: package_id.package_name.clone(),
|
||||||
|
publisher_node: package_id.publisher_node.clone(),
|
||||||
|
},
|
||||||
download_from: download_from.clone(),
|
download_from: download_from.clone(),
|
||||||
mirror: true,
|
mirror: true,
|
||||||
auto_update: true,
|
auto_update: true,
|
||||||
desired_version_hash: None,
|
desired_version_hash: None,
|
||||||
})
|
}))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
.send_and_await_response(5)
|
.send_and_await_response(5)
|
||||||
@ -60,7 +64,7 @@ fn init(our: Address) {
|
|||||||
LocalResponse::DownloadResponse(DownloadResponse::Started) => {
|
LocalResponse::DownloadResponse(DownloadResponse::Started) => {
|
||||||
println!("started downloading package {package_id} from {download_from}");
|
println!("started downloading package {package_id} from {download_from}");
|
||||||
}
|
}
|
||||||
LocalResponse::DownloadResponse(DownloadResponse::Failure) => {
|
LocalResponse::DownloadResponse(_) => {
|
||||||
println!("failed to download package {package_id} from {download_from}");
|
println!("failed to download package {package_id} from {download_from}");
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -8,7 +8,7 @@ simulation-mode = []
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "09dc9f9" }
|
kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "9998921" }
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
wit-bindgen = "0.24.0"
|
wit-bindgen = "0.24.0"
|
||||||
|
@ -1 +0,0 @@
|
|||||||
../../app_store/src/api.rs
|
|
@ -1,13 +1,13 @@
|
|||||||
|
use crate::kinode::process::main::{InstallResponse, LocalRequest, LocalResponse};
|
||||||
use kinode_process_lib::{
|
use kinode_process_lib::{
|
||||||
await_next_message_body, call_init, println, Address, Message, PackageId, Request,
|
await_next_message_body, call_init, println, Address, Message, PackageId, Request,
|
||||||
};
|
};
|
||||||
|
|
||||||
mod api;
|
|
||||||
use api::*;
|
|
||||||
|
|
||||||
wit_bindgen::generate!({
|
wit_bindgen::generate!({
|
||||||
path: "target/wit",
|
path: "target/wit",
|
||||||
world: "process-v0",
|
generate_unused_types: true,
|
||||||
|
world: "app-store-sys-v0",
|
||||||
|
additional_derives: [PartialEq, serde::Deserialize, serde::Serialize],
|
||||||
});
|
});
|
||||||
|
|
||||||
call_init!(init);
|
call_init!(init);
|
||||||
@ -33,7 +33,15 @@ fn init(our: Address) {
|
|||||||
|
|
||||||
let Ok(Ok(Message::Response { body, .. })) =
|
let Ok(Ok(Message::Response { body, .. })) =
|
||||||
Request::to((our.node(), ("main", "app_store", "sys")))
|
Request::to((our.node(), ("main", "app_store", "sys")))
|
||||||
.body(serde_json::to_vec(&LocalRequest::Install(package_id.clone())).unwrap())
|
.body(
|
||||||
|
serde_json::to_vec(&LocalRequest::Install(
|
||||||
|
crate::kinode::process::main::PackageId {
|
||||||
|
package_name: package_id.package_name.clone(),
|
||||||
|
publisher_node: package_id.publisher_node.clone(),
|
||||||
|
},
|
||||||
|
))
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
.send_and_await_response(5)
|
.send_and_await_response(5)
|
||||||
else {
|
else {
|
||||||
println!("install: failed to get a response from app_store..!");
|
println!("install: failed to get a response from app_store..!");
|
||||||
|
@ -8,7 +8,7 @@ simulation-mode = []
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "09dc9f9" }
|
kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "9998921" }
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
wit-bindgen = "0.24.0"
|
wit-bindgen = "0.24.0"
|
||||||
|
@ -1 +0,0 @@
|
|||||||
../../app_store/src/api.rs
|
|
@ -1,13 +1,13 @@
|
|||||||
|
use crate::kinode::process::main::{LocalRequest, LocalResponse, UninstallResponse};
|
||||||
use kinode_process_lib::{
|
use kinode_process_lib::{
|
||||||
await_next_message_body, call_init, println, Address, Message, PackageId, Request,
|
await_next_message_body, call_init, println, Address, Message, PackageId, Request,
|
||||||
};
|
};
|
||||||
|
|
||||||
mod api;
|
|
||||||
use api::*;
|
|
||||||
|
|
||||||
wit_bindgen::generate!({
|
wit_bindgen::generate!({
|
||||||
path: "target/wit",
|
path: "target/wit",
|
||||||
world: "process-v0",
|
generate_unused_types: true,
|
||||||
|
world: "app-store-sys-v0",
|
||||||
|
additional_derives: [PartialEq, serde::Deserialize, serde::Serialize],
|
||||||
});
|
});
|
||||||
|
|
||||||
call_init!(init);
|
call_init!(init);
|
||||||
@ -33,7 +33,15 @@ fn init(our: Address) {
|
|||||||
|
|
||||||
let Ok(Ok(Message::Response { body, .. })) =
|
let Ok(Ok(Message::Response { body, .. })) =
|
||||||
Request::to((our.node(), ("main", "app_store", "sys")))
|
Request::to((our.node(), ("main", "app_store", "sys")))
|
||||||
.body(serde_json::to_vec(&LocalRequest::Uninstall(package_id.clone())).unwrap())
|
.body(
|
||||||
|
serde_json::to_vec(&LocalRequest::Uninstall(
|
||||||
|
crate::kinode::process::main::PackageId {
|
||||||
|
package_name: package_id.package_name.clone(),
|
||||||
|
publisher_node: package_id.publisher_node.clone(),
|
||||||
|
},
|
||||||
|
))
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
.send_and_await_response(5)
|
.send_and_await_response(5)
|
||||||
else {
|
else {
|
||||||
println!("uninstall: failed to get a response from app_store..!");
|
println!("uninstall: failed to get a response from app_store..!");
|
||||||
|
Loading…
Reference in New Issue
Block a user