Skip to content

Commit

Permalink
Merge pull request #178 from kinode-dao/bp/kinomap
Browse files Browse the repository at this point in the history
0.9 kimap
  • Loading branch information
nick1udwig authored Aug 21, 2024
2 parents fef05c3 + 0ff5fa5 commit ed7a0e7
Show file tree
Hide file tree
Showing 14 changed files with 1,834 additions and 232 deletions.
1,149 changes: 1,080 additions & 69 deletions Cargo.lock

Large diffs are not rendered by default.

25 changes: 24 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,34 @@
[package]
name = "kit"
version = "0.6.11"
version = "0.7.0"
edition = "2021"

[build-dependencies]
anyhow = "1.0"
git2 = "0.18"

[dependencies]
alloy = { version = "0.1.3", features = [
"consensus",
"contract",
"json-rpc",
"network",
"provider-ws",
"providers",
"pubsub",
"rpc",
"rpc-client",
"rpc-client-ws",
"rpc-types",
"rpc-types-eth",
"signers",
"signer-keystore",
"signer-ledger",
"signer-local",
"signer-trezor",
] }
alloy-sol-macro = "0.7.6"
alloy-sol-types = "0.7.6"
base64 = "0.21"
clap = { version = "4.4", features = ["cargo", "string"] }
color-eyre = { version = "0.6", features = ["capture-spantrace"] }
Expand All @@ -18,6 +39,8 @@ kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib.git", re
nix = { version = "0.27", features = ["process", "signal", "term"] }
regex = "1"
reqwest = { version = "0.12", features = ["json"] }
# rmp-serde = "1.1.2"
rpassword = "7"
semver = "1.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
Expand Down
7 changes: 1 addition & 6 deletions src/boot_fake_node/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -448,12 +448,7 @@ pub async fn execute(
let send_to_cleanup_for_cleanup = send_to_cleanup.clone();
let _cleanup_context = CleanupContext::new(send_to_cleanup_for_cleanup);

// TODO: change this to be less restrictive; currently leads to weirdness
// like an input of `fake.os` -> `fake.os.dev`.
// The reason we need it for now is that non-`.dev` nodes are not currently
// addressable.
// Once they are addressable, change this to, perhaps, `!name.contains(".")
if !fake_node_name.ends_with(".dev") {
if !fake_node_name.contains(".") {
fake_node_name.push_str(".dev");
}

Expand Down
87 changes: 83 additions & 4 deletions src/build/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::collections::{HashMap, HashSet};
use std::io::{Read, Write};
use std::path::{Path, PathBuf};
use std::process::Command;
use std::time::SystemTime;
Expand All @@ -12,15 +13,17 @@ use color_eyre::{
};
use fs_err as fs;
use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
use tracing::{debug, info, instrument, warn};
use walkdir::WalkDir;
use zip::write::FileOptions;

use kinode_process_lib::{PackageId, kernel_types::Erc721Metadata};

use crate::setup::{
check_js_deps, check_py_deps, check_rust_deps, get_deps, get_newest_valid_node_version,
get_python_version, REQUIRED_PY_PACKAGE,
};
use crate::start_package::zip_directory;
use crate::view_api;
use crate::KIT_CACHE;

Expand All @@ -46,6 +49,75 @@ struct CargoPackage {
name: String,
}

pub fn make_pkg_publisher(metadata: &Erc721Metadata) -> String {
let package_name = metadata.properties.package_name.as_str();
let publisher = metadata.properties.publisher.as_str();
let pkg_publisher = format!("{}:{}", package_name, publisher);
pkg_publisher
}

pub fn make_zip_filename(package_dir: &Path, pkg_publisher: &str) -> PathBuf {
let zip_filename = package_dir.join("target").join(pkg_publisher).with_extension("zip");
zip_filename
}

#[instrument(level = "trace", skip_all)]
pub fn hash_zip_pkg(zip_path: &Path) -> Result<String> {
let mut file = fs::File::open(&zip_path)?;
let mut hasher = Sha256::new();
let mut buffer = Vec::new();
file.read_to_end(&mut buffer)?;
hasher.update(&buffer);
let hash_result = hasher.finalize();
Ok(format!("{hash_result:x}"))
}

#[instrument(level = "trace", skip_all)]
pub fn zip_pkg(package_dir: &Path, pkg_publisher: &str) -> Result<(PathBuf, String)> {
let pkg_dir = package_dir.join("pkg");
let target_dir = package_dir.join("target");
fs::create_dir_all(&target_dir)?;
let zip_filename = make_zip_filename(package_dir, pkg_publisher);
zip_directory(&pkg_dir, &zip_filename.to_str().unwrap())?;

let hash = hash_zip_pkg(&zip_filename)?;
Ok((zip_filename, hash))
}

#[instrument(level = "trace", skip_all)]
fn zip_directory(directory: &Path, zip_filename: &str) -> Result<()> {
let file = fs::File::create(zip_filename)?;
let walkdir = WalkDir::new(directory);
let it = walkdir.into_iter();

let mut zip = zip::ZipWriter::new(file);

let options = FileOptions::default()
.compression_method(zip::CompressionMethod::Deflated)
.unix_permissions(0o755)
.last_modified_time(zip::DateTime::from_date_and_time(1980, 1, 1, 0, 0, 0).unwrap());

for entry in it {
let entry = entry?;
let path = entry.path();
let name = path.strip_prefix(Path::new(directory))?;

if path.is_file() {
zip.start_file(name.to_string_lossy(), options)?;
let mut f = fs::File::open(path)?;
let mut buffer = Vec::new();
f.read_to_end(&mut buffer)?;
zip.write_all(&*buffer)?;
} else if name.as_os_str().len() != 0 {
// Only if it is not the root directory
zip.add_directory(name.to_string_lossy(), options)?;
}
}

zip.finish()?;
Ok(())
}

#[instrument(level = "trace", skip_all)]
pub fn has_feature(cargo_toml_path: &str, feature: &str) -> Result<bool> {
let cargo_toml_content = fs::read_to_string(cargo_toml_path)?;
Expand Down Expand Up @@ -1200,7 +1272,7 @@ pub async fn execute(
verbose,
ignore_deps,
)
.await
.await?;
}
} else {
if no_ui {
Expand All @@ -1225,7 +1297,7 @@ pub async fn execute(
let valid_node = get_newest_valid_node_version(None, None)?;

if ui_only {
compile_and_copy_ui(package_dir, valid_node, verbose).await
compile_and_copy_ui(package_dir, valid_node, verbose).await?;
} else {
compile_package_and_ui(
package_dir,
Expand All @@ -1241,7 +1313,14 @@ pub async fn execute(
verbose,
ignore_deps,
)
.await
.await?;
}
}

let metadata = read_metadata(package_dir)?;
let pkg_publisher = make_pkg_publisher(&metadata);
let (_zip_filename, hash_string) = zip_pkg(package_dir, &pkg_publisher)?;
info!("package zip hash: {hash_string}");

Ok(())
}
2 changes: 1 addition & 1 deletion src/chain/kinostate.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub mod connect;
pub mod dev_ui;
pub mod inject_message;
pub mod new;
pub mod publish;
pub mod remove_package;
pub mod reset_cache;
pub mod run_tests;
Expand Down
133 changes: 126 additions & 7 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ use tracing_subscriber::{

use kit::{
boot_fake_node, boot_real_node, build, build_start_package, chain, connect, dev_ui,
inject_message, new, remove_package, reset_cache, run_tests, setup, start_package, update,
view_api, KIT_LOG_PATH_DEFAULT,
inject_message, new, publish, remove_package, reset_cache, run_tests, setup, start_package,
update, view_api, KIT_LOG_PATH_DEFAULT,
};

const MAX_REMOTE_VALUES: usize = 3;
Expand All @@ -36,6 +36,11 @@ struct Commit {
sha: String,
}

fn parse_u128_with_underscores(s: &str) -> Result<u128, &'static str> {
let clean_string = s.replace('_', "");
clean_string.parse::<u128>().map_err(|_| "Invalid number format")
}

async fn get_latest_commit_sha_from_branch(
owner: &str,
repo: &str,
Expand Down Expand Up @@ -330,6 +335,39 @@ async fn execute(
*ui,
)
}
Some(("publish", matches)) => {
let package_dir = PathBuf::from(matches.get_one::<String>("DIR").unwrap());
let metadata_uri = matches.get_one::<String>("URI").unwrap();
let keystore_path = matches
.get_one::<String>("PATH")
.and_then(|kp| Some(PathBuf::from(kp)));
let ledger = matches.get_one::<bool>("LEDGER").unwrap();
let trezor = matches.get_one::<bool>("TREZOR").unwrap();
let rpc_uri = matches.get_one::<String>("RPC_URI").unwrap();
let real = matches.get_one::<bool>("REAL").unwrap();
let unpublish = matches.get_one::<bool>("UNPUBLISH").unwrap();
let gas_limit = matches.get_one::<u128>("GAS_LIMIT").unwrap();
let max_priority_fee = matches
.get_one::<u128>("MAX_PRIORITY_FEE_PER_GAS")
.and_then(|mpf| Some(mpf.clone()));
let max_fee_per_gas = matches
.get_one::<u128>("MAX_FEE_PER_GAS")
.and_then(|mfpg| Some(mfpg.clone()));

publish::execute(
&package_dir,
metadata_uri,
keystore_path,
ledger,
trezor,
rpc_uri,
real,
unpublish,
*gas_limit,
max_priority_fee,
max_fee_per_gas,
).await
}
Some(("remove-package", matches)) => {
let package_name = matches
.get_one::<String>("PACKAGE")
Expand Down Expand Up @@ -483,7 +521,7 @@ async fn make_app(current_dir: &std::ffi::OsString) -> Result<Command> {
.arg(Arg::new("RPC_ENDPOINT")
.action(ArgAction::Set)
.long("rpc")
.help("Ethereum RPC endpoint (wss://)")
.help("Ethereum Optimism mainnet RPC endpoint (wss://)")
.required(false)
)
.arg(Arg::new("PERSIST")
Expand Down Expand Up @@ -560,7 +598,7 @@ async fn make_app(current_dir: &std::ffi::OsString) -> Result<Command> {
.arg(Arg::new("RPC_ENDPOINT")
.action(ArgAction::Set)
.long("rpc")
.help("Ethereum RPC endpoint (wss://)")
.help("Ethereum Optimism mainnet RPC endpoint (wss://)")
.required(false)
)
//.arg(Arg::new("PASSWORD") // TODO: with develop 0.8.0
Expand Down Expand Up @@ -777,7 +815,7 @@ async fn make_app(current_dir: &std::ffi::OsString) -> Result<Command> {
.action(ArgAction::SetTrue)
.short('d')
.long("disconnect")
.help("If set, disconnect an existing tunnel (default: connect a new tunnel)")
.help("If set, disconnect an existing tunnel [default: connect a new tunnel]")
.required(false)
)
.arg(Arg::new("HOST")
Expand Down Expand Up @@ -850,7 +888,7 @@ async fn make_app(current_dir: &std::ffi::OsString) -> Result<Command> {
.action(ArgAction::Set)
.short('n')
.long("node")
.help("Node ID (default: our)")
.help("Node ID [default: our]")
.required(false)
)
.arg(Arg::new("PATH")
Expand Down Expand Up @@ -911,6 +949,87 @@ async fn make_app(current_dir: &std::ffi::OsString) -> Result<Command> {
.required(false)
)
)
.subcommand(Command::new("publish")
.about("Publish or update a package")
.visible_alias("p")
.arg(Arg::new("DIR")
.action(ArgAction::Set)
.help("The package directory to publish")
.default_value(current_dir)
)
.arg(Arg::new("PATH")
.action(ArgAction::Set)
.short('k')
.long("keystore-path")
.help("Path to private key keystore (choose 1 of `k`, `l`, `t`)") // TODO: add link to docs?
.required(false)
)
.arg(Arg::new("LEDGER")
.action(ArgAction::SetTrue)
.short('l')
.long("ledger")
.help("Use Ledger private key (choose 1 of `k`, `l`, `t`)")
.required(false)
)
.arg(Arg::new("TREZOR")
.action(ArgAction::SetTrue)
.short('t')
.long("trezor")
.help("Use Trezor private key (choose 1 of `k`, `l`, `t`)")
.required(false)
)
.arg(Arg::new("URI")
.action(ArgAction::Set)
.short('u')
.long("metadata-uri")
.help("URI where metadata lives")
.required(true)
)
.arg(Arg::new("RPC_URI")
.action(ArgAction::Set)
.short('r')
.long("rpc")
.help("Ethereum Optimism mainnet RPC endpoint (wss://)")
.required(true)
)
.arg(Arg::new("REAL")
.action(ArgAction::SetTrue)
.short('e')
.long("real")
.help("If set, deploy to real network [default: fake node]")
.required(false)
)
.arg(Arg::new("UNPUBLISH")
.action(ArgAction::SetTrue)
.long("unpublish")
.help("If set, unpublish existing published package [default: publish a package]")
)
.arg(Arg::new("GAS_LIMIT")
.action(ArgAction::Set)
.short('g')
.long("gas-limit")
.help("The ETH transaction gas limit")
.default_value("1_000_000")
.value_parser(clap::builder::ValueParser::new(parse_u128_with_underscores))
.required(false)
)
.arg(Arg::new("MAX_PRIORITY_FEE_PER_GAS")
.action(ArgAction::Set)
.short('p')
.long("priority-fee")
.help("The ETH transaction max priority fee per gas [default: estimated from network conditions]")
.value_parser(clap::builder::ValueParser::new(parse_u128_with_underscores))
.required(false)
)
.arg(Arg::new("MAX_FEE_PER_GAS")
.action(ArgAction::Set)
.short('f')
.long("fee-per-gas")
.help("The ETH transaction max fee per gas [default: estimated from network conditions]")
.value_parser(clap::builder::ValueParser::new(parse_u128_with_underscores))
.required(false)
)
)
.subcommand(Command::new("remove-package")
.about("Remove a running package from a node")
.visible_alias("r")
Expand Down Expand Up @@ -1000,7 +1119,7 @@ async fn make_app(current_dir: &std::ffi::OsString) -> Result<Command> {
.visible_alias("v")
.arg(Arg::new("PACKAGE_ID")
.action(ArgAction::Set)
.help("Get API of this package (default: list all APIs)")
.help("Get API of this package [default: list all APIs]")
.required(false)
)
.arg(Arg::new("NODE_PORT")
Expand Down
Loading

0 comments on commit ed7a0e7

Please sign in to comment.