From 1036d6c4697145217ed4f0aac85b2aedec278975 Mon Sep 17 00:00:00 2001 From: rustonbsd Date: Sun, 26 Oct 2025 10:32:25 +0100 Subject: [PATCH 1/2] updated iroh to 0.94 --- crates/rustpatcher/Cargo.toml | 14 +++++++------- crates/rustpatcher/src/distributor.rs | 18 ++++++++--------- crates/rustpatcher/src/patch.rs | 5 ++--- crates/rustpatcher/src/patcher.rs | 23 +++++++++++----------- crates/rustpatcher/src/publisher.rs | 22 ++++++++++----------- crates/rustpatcher/src/updater.rs | 28 +++++++++++++-------------- crates/rustpatcher/xtask/sign.rs | 4 ++-- 7 files changed, 57 insertions(+), 57 deletions(-) diff --git a/crates/rustpatcher/Cargo.toml b/crates/rustpatcher/Cargo.toml index f9e9238..da6a24e 100644 --- a/crates/rustpatcher/Cargo.toml +++ b/crates/rustpatcher/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustpatcher" -version = "0.2.1" +version = "0.2.2" edition = "2024" description = "distributed patching system for single binary applications" license = "MIT" @@ -14,15 +14,15 @@ categories = ["network-programming"] [dependencies] rustpatcher_macros = { path = "../rustpatcher-macros", package = "rustpatcher-macros", version = "0.2.0" } -ctor = "0.5" -actor-helper = "0.1" +ctor = "0.6" +actor-helper = { version = "0.2", features = ["tokio","anyhow"] } tokio ={ version = "1", features = ["rt-multi-thread","macros","sync"] } anyhow = "1" serde = { version = "1", default-features = false, features = ["derive"] } serde_json = "1" -ed25519-dalek = { version = "2", features = ["serde", "rand_core"] } +ed25519-dalek = { version = "3.0.0-pre.1", features = ["serde", "rand_core"] } sha2 = "0.10" -rand = "0.8" +rand = "0.9" z32 = "1" clap = { version = "4", features = ["derive"] } once_cell = "1" @@ -34,10 +34,10 @@ chrono = { version = "0.4", default-features = false, features = ["std"] } tracing = "0.1" tracing-subscriber = { version = "0.3", default-features=false, features = ["std"] } -iroh = { version = "0.92", default-features = false } +iroh = { version = "0.94", default-features = false } postcard = { version = "1" } -distributed-topic-tracker = { version="0.2.1", default-features = false } +distributed-topic-tracker = { version="0.2.4", default-features = false } [[example]] name = "platforms" diff --git a/crates/rustpatcher/src/distributor.rs b/crates/rustpatcher/src/distributor.rs index ee2ccfb..f1a4f9f 100644 --- a/crates/rustpatcher/src/distributor.rs +++ b/crates/rustpatcher/src/distributor.rs @@ -1,7 +1,7 @@ -use actor_helper::{Action, Actor, Handle, act_ok}; +use actor_helper::{act_ok, Action, Actor, Handle, Receiver}; use distributed_topic_tracker::unix_minute; use iroh::{ - Endpoint, NodeId, + Endpoint, EndpointId, endpoint::VarInt, protocol::{AcceptError, ProtocolHandler}, }; @@ -13,12 +13,12 @@ use crate::{Patch, PatchInfo}; #[derive(Debug, Clone)] pub struct Distributor { - api: Handle, + api: Handle, } #[derive(Debug)] struct DistributorActor { - rx: tokio::sync::mpsc::Receiver>, + rx: Receiver>, self_patch_bytes: Vec, endpoint: Endpoint, @@ -27,7 +27,7 @@ struct DistributorActor { impl Distributor { pub fn new(endpoint: Endpoint) -> anyhow::Result { let self_patch_bytes = postcard::to_allocvec(&Patch::from_self()?)?; - let (api, rx) = Handle::channel(32); + let (api, rx) = Handle::channel(); tokio::spawn(async move { let mut actor = DistributorActor { rx, @@ -50,7 +50,7 @@ impl Distributor { .into_bytes() } - pub async fn get_patch(&self, node_id: NodeId, patch_info: PatchInfo) -> anyhow::Result { + pub async fn get_patch(&self, endpoint_id: EndpointId, patch_info: PatchInfo) -> anyhow::Result { let endpoint = self .api .call(act_ok!(actor => async move { @@ -58,7 +58,7 @@ impl Distributor { })) .await?; - let conn = endpoint.connect(node_id, &Distributor::ALPN()).await?; + let conn = endpoint.connect(endpoint_id, &Distributor::ALPN()).await?; let (mut tx, mut rx) = conn.open_bi().await?; // auth: hash(owner_pub_key + unix_minute) @@ -88,11 +88,11 @@ impl Distributor { } } -impl Actor for DistributorActor { +impl Actor for DistributorActor { async fn run(&mut self) -> anyhow::Result<()> { loop { tokio::select! { - Some(action) = self.rx.recv() => { + Ok(action) = self.rx.recv_async() => { action(self).await } } diff --git a/crates/rustpatcher/src/patch.rs b/crates/rustpatcher/src/patch.rs index c36162e..79056da 100644 --- a/crates/rustpatcher/src/patch.rs +++ b/crates/rustpatcher/src/patch.rs @@ -1,5 +1,5 @@ use crate::Version; -use ed25519_dalek::{Signature, SigningKey, ed25519::signature::SignerMut}; +use ed25519_dalek::{Signature, Signer, SigningKey}; use serde::{Deserialize, Serialize}; use sha2::Digest; @@ -75,7 +75,6 @@ impl Patch { crate::embed::cut_embed_section(data_stripped)?; let version = crate::embed::get_embedded_version(&data_embed)?; - let mut owner_siging_key = owner_signing_key; let mut data_hasher = sha2::Sha512::new(); data_hasher.update(data_no_embed.as_slice()); let data_hash = data_hasher.finalize()[..32].try_into()?; @@ -85,7 +84,7 @@ impl Patch { sign_hash.update(data_hash); sign_hash.update((data_no_embed.len() as u64).to_le_bytes()); let sign_hash = sign_hash.finalize(); - let signature = owner_siging_key.sign(&sign_hash); + let signature = owner_signing_key.sign(&sign_hash); Ok(PatchInfo { version, diff --git a/crates/rustpatcher/src/patcher.rs b/crates/rustpatcher/src/patcher.rs index 9bede6e..4549d40 100644 --- a/crates/rustpatcher/src/patcher.rs +++ b/crates/rustpatcher/src/patcher.rs @@ -1,7 +1,8 @@ use std::{str::FromStr, sync::Mutex}; -use actor_helper::{Action, Actor, Handle}; +use actor_helper::{Action, Actor, Handle, Receiver}; use distributed_topic_tracker::{RecordPublisher, RecordTopic}; +use ed25519_dalek::SigningKey; use iroh::{Endpoint, protocol::Router}; use once_cell::sync::OnceCell; use sha2::Digest; @@ -49,7 +50,9 @@ impl Builder { #[cfg_attr(debug_assertions, allow(dead_code))] pub async fn build(self) -> anyhow::Result { - let secret_key = iroh::SecretKey::generate(rand::rngs::OsRng); + let secret_key = iroh::SecretKey::generate(&mut rand::rng()); + let signing_key = SigningKey::from_bytes(&secret_key.to_bytes()); + let topic_id = RecordTopic::from_str( format!( "rustpatcher:{}", @@ -64,8 +67,8 @@ impl Builder { let record_publisher = RecordPublisher::new( topic_id, - secret_key.public().public(), - secret_key.secret().clone(), + signing_key.verifying_key(), + signing_key, None, initial_secret, ); @@ -75,8 +78,6 @@ impl Builder { let endpoint = Endpoint::builder() .secret_key(secret_key.clone()) - //.add_discovery(DnsDiscovery::n0_dns()) - .discovery_n0() .bind() .await?; @@ -99,12 +100,12 @@ impl Builder { #[derive(Debug, Clone)] pub struct Patcher { - _api: Handle, + _api: Handle, } #[derive(Debug)] struct PatcherActor { - rx: tokio::sync::mpsc::Receiver>, + rx: Receiver>, publisher: Publisher, updater: Option, @@ -131,7 +132,7 @@ impl Patcher { endpoint: Endpoint, router: Router, ) -> Self { - let (api, rx) = Handle::channel(32); + let (api, rx) = Handle::channel(); tokio::spawn(async move { let mut actor = PatcherActor { rx, @@ -152,11 +153,11 @@ impl Patcher { } } -impl Actor for PatcherActor { +impl Actor for PatcherActor { async fn run(&mut self) -> anyhow::Result<()> { loop { tokio::select! { - Some(action) = self.rx.recv() => { + Ok(action) = self.rx.recv_async() => { action(self).await } Some(_) = self.update_receiver.recv(), if self.updater.is_none() => { diff --git a/crates/rustpatcher/src/publisher.rs b/crates/rustpatcher/src/publisher.rs index c504ba7..c5904cc 100644 --- a/crates/rustpatcher/src/publisher.rs +++ b/crates/rustpatcher/src/publisher.rs @@ -1,13 +1,13 @@ -use actor_helper::{Action, Actor, Handle, act_ok}; +use actor_helper::{act_ok, Action, Actor, Handle, Receiver}; use distributed_topic_tracker::{RecordPublisher, unix_minute}; -use iroh::NodeId; +use iroh::EndpointId; use tracing::{debug, error, warn}; use crate::{Patch, PatchInfo, Version}; #[derive(Debug, Clone)] pub struct Publisher { - api: Handle, + api: Handle, } #[derive(Debug, Clone)] @@ -18,7 +18,7 @@ pub enum PublisherState { #[derive(Debug)] struct PublisherActor { - rx: tokio::sync::mpsc::Receiver>, + rx: Receiver>, state: PublisherState, interval: tokio::time::Interval, @@ -34,7 +34,7 @@ impl Publisher { update_starter: tokio::sync::mpsc::Sender<()>, ) -> anyhow::Result { let self_patch = Patch::from_self()?; - let (api, rx) = Handle::channel(32); + let (api, rx) = Handle::channel(); tokio::spawn(async move { let mut interval = tokio::time::interval(tokio::time::Duration::from_secs(55)); interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip); @@ -63,11 +63,11 @@ impl Publisher { } } -impl Actor for PublisherActor { +impl Actor for PublisherActor { async fn run(&mut self) -> anyhow::Result<()> { loop { tokio::select! { - Some(action) = self.rx.recv() => { + Ok(action) = self.rx.recv_async() => { action(self).await } _ = self.interval.tick(), if matches!(self.state, PublisherState::Publishing) => { @@ -80,9 +80,9 @@ impl Actor for PublisherActor { let newer_patch_infos = records .iter() .filter_map(|r| if let Ok(patch_info) = r.content::(){ - if let Ok(node_id) = NodeId::from_bytes(&r.node_id()) { - warn!("Found patch info: {:?}{:?}", node_id,patch_info); - Some((node_id,patch_info.clone())) + if let Ok(endpoint_id) = EndpointId::from_bytes(&r.node_id()) { + warn!("Found patch info: {:?}{:?}", endpoint_id,patch_info); + Some((endpoint_id,patch_info.clone())) } else { None } @@ -90,7 +90,7 @@ impl Actor for PublisherActor { None }) .filter(|(_,p)| p.version > c_version) - .collect::>(); + .collect::>(); warn!("Checked for updates, found {} newer versions", newer_patch_infos.len()); if newer_patch_infos.is_empty() { diff --git a/crates/rustpatcher/src/updater.rs b/crates/rustpatcher/src/updater.rs index 2d37aa4..25acbdb 100644 --- a/crates/rustpatcher/src/updater.rs +++ b/crates/rustpatcher/src/updater.rs @@ -5,10 +5,10 @@ use std::{ process, ptr, }; -use actor_helper::{Action, Actor, Handle}; +use actor_helper::{Action, Actor, Handle, Receiver}; use chrono::Timelike; use distributed_topic_tracker::{RecordPublisher, unix_minute}; -use iroh::NodeId; +use iroh::EndpointId; use nix::libc; use tracing::{error, info}; @@ -23,12 +23,12 @@ pub enum UpdaterMode { #[derive(Debug, Clone)] pub struct Updater { - _api: Handle, + _api: Handle, } #[derive(Debug)] struct UpdaterActor { - rx: tokio::sync::mpsc::Receiver>, + rx: Receiver>, distributor: Distributor, mode: UpdaterMode, @@ -45,7 +45,7 @@ impl Updater { distributor: Distributor, record_publisher: RecordPublisher, ) -> Self { - let (api, rx) = Handle::channel(32); + let (api, rx) = Handle::channel(); tokio::spawn(async move { let mut try_update_interval = tokio::time::interval(tokio::time::Duration::from_secs(56)); @@ -68,11 +68,11 @@ impl Updater { } } -impl Actor for UpdaterActor { +impl Actor for UpdaterActor { async fn run(&mut self) -> anyhow::Result<()> { loop { tokio::select! { - Some(action) = self.rx.recv() => { + Ok(action) = self.rx.recv_async() => { action(self).await } _ = self.try_update_interval.tick() => { @@ -108,7 +108,7 @@ impl Actor for UpdaterActor { } impl UpdaterActor { - async fn check_for_updates(&mut self) -> anyhow::Result> { + async fn check_for_updates(&mut self) -> anyhow::Result> { let now = unix_minute(0); let mut records = self.record_publisher.get_records(now).await; records.extend(self.record_publisher.get_records(now - 1).await); @@ -117,8 +117,8 @@ impl UpdaterActor { .iter() .filter_map(|r| { if let Ok(patch_info) = r.content::() { - if let Ok(node_id) = NodeId::from_bytes(&r.node_id()) { - Some((node_id, patch_info.clone())) + if let Ok(endpoint_id) = EndpointId::from_bytes(&r.node_id()) { + Some((endpoint_id, patch_info.clone())) } else { None } @@ -127,7 +127,7 @@ impl UpdaterActor { } }) .filter(|(_, p)| p.version > c_version) - .collect::>(); + .collect::>(); if newer_patch_infos.is_empty() { return Ok(vec![]); @@ -145,11 +145,11 @@ impl UpdaterActor { async fn try_download_patch( &mut self, - node_id: NodeId, + endpoint_id: EndpointId, patch_info: PatchInfo, ) -> anyhow::Result<()> { - info!("Downloading patch {:?} from {:?}", patch_info, node_id); - let res = self.distributor.get_patch(node_id, patch_info).await; + info!("Downloading patch {:?} from {:?}", patch_info, endpoint_id); + let res = self.distributor.get_patch(endpoint_id, patch_info).await; info!("Downloaded patch: {:?}", res.is_ok()); let patch = res?; self.newer_patch = Some(patch.clone()); diff --git a/crates/rustpatcher/xtask/sign.rs b/crates/rustpatcher/xtask/sign.rs index e93bd82..36b5751 100644 --- a/crates/rustpatcher/xtask/sign.rs +++ b/crates/rustpatcher/xtask/sign.rs @@ -48,7 +48,7 @@ fn main() -> anyhow::Result<()> { } fn generate_key_cmd(key_file: std::path::PathBuf) -> anyhow::Result<()> { - let signing_key = SigningKey::generate(&mut rand::thread_rng()); + let signing_key = SigningKey::generate(&mut rand::rng()); let signing_key_z32 = z32::encode(signing_key.as_bytes()); let signing_key_bytes = signing_key_z32.as_bytes(); @@ -145,7 +145,7 @@ fn load_signing_key(source: KeySource) -> anyhow::Result { let data = if let Ok(data) = fs::read(&path) { data } else { - let signing_key = SigningKey::generate(&mut rand::thread_rng()); + let signing_key = SigningKey::generate(&mut rand::rng()); let signing_key_z32 = z32::encode(signing_key.as_bytes()); let signing_key_bytes = signing_key_z32.as_bytes(); fs::write(&path, signing_key_bytes)?; From 4e1e9503a819fadcc322f3fa7cb70e4de0d2dca0 Mon Sep 17 00:00:00 2001 From: rustonbsd Date: Sun, 26 Oct 2025 10:32:46 +0100 Subject: [PATCH 2/2] fmt --- crates/rustpatcher-macros/src/lib.rs | 4 ++-- crates/rustpatcher/e2e_test/e2e.rs | 1 - crates/rustpatcher/examples/platforms.rs | 1 - crates/rustpatcher/src/distributor.rs | 8 ++++++-- crates/rustpatcher/src/embed.rs | 5 ++++- crates/rustpatcher/src/macho.rs | 7 ++++--- crates/rustpatcher/src/patch.rs | 9 ++------- crates/rustpatcher/src/publisher.rs | 2 +- crates/rustpatcher/xtask/sign.rs | 5 ++--- 9 files changed, 21 insertions(+), 21 deletions(-) diff --git a/crates/rustpatcher-macros/src/lib.rs b/crates/rustpatcher-macros/src/lib.rs index 7e8cb27..fdf6943 100644 --- a/crates/rustpatcher-macros/src/lib.rs +++ b/crates/rustpatcher-macros/src/lib.rs @@ -1,6 +1,6 @@ use proc_macro::TokenStream; use quote::quote; -use syn::{parse_macro_input, ItemFn, Expr}; +use syn::{Expr, ItemFn, parse_macro_input}; #[proc_macro_attribute] pub fn public_key(args: TokenStream, input: TokenStream) -> TokenStream { @@ -27,4 +27,4 @@ pub fn public_key(args: TokenStream, input: TokenStream) -> TokenStream { }; TokenStream::from(expanded) -} \ No newline at end of file +} diff --git a/crates/rustpatcher/e2e_test/e2e.rs b/crates/rustpatcher/e2e_test/e2e.rs index 91c2eab..d184920 100644 --- a/crates/rustpatcher/e2e_test/e2e.rs +++ b/crates/rustpatcher/e2e_test/e2e.rs @@ -8,7 +8,6 @@ const PUBLIC_KEY: &str = "bhafqhm8k9e7fzab7i7h6gie6oedncwyffautkngqsa9d1ohzuho"; #[tokio::main] #[rustpatcher::public_key(PUBLIC_KEY)] async fn main() -> anyhow::Result<()> { - rustpatcher::spawn(rustpatcher::UpdaterMode::Now).await?; println!("{:?}", rustpatcher::Version::current()?); diff --git a/crates/rustpatcher/examples/platforms.rs b/crates/rustpatcher/examples/platforms.rs index 19bd228..6cf4381 100644 --- a/crates/rustpatcher/examples/platforms.rs +++ b/crates/rustpatcher/examples/platforms.rs @@ -13,7 +13,6 @@ async fn main() -> anyhow::Result<()> { .with_thread_ids(true) .init(); - #[cfg(not(debug_assertions))] { rustpatcher::spawn(rustpatcher::UpdaterMode::At(13, 40)).await?; diff --git a/crates/rustpatcher/src/distributor.rs b/crates/rustpatcher/src/distributor.rs index f1a4f9f..f0a2475 100644 --- a/crates/rustpatcher/src/distributor.rs +++ b/crates/rustpatcher/src/distributor.rs @@ -1,4 +1,4 @@ -use actor_helper::{act_ok, Action, Actor, Handle, Receiver}; +use actor_helper::{Action, Actor, Handle, Receiver, act_ok}; use distributed_topic_tracker::unix_minute; use iroh::{ Endpoint, EndpointId, @@ -50,7 +50,11 @@ impl Distributor { .into_bytes() } - pub async fn get_patch(&self, endpoint_id: EndpointId, patch_info: PatchInfo) -> anyhow::Result { + pub async fn get_patch( + &self, + endpoint_id: EndpointId, + patch_info: PatchInfo, + ) -> anyhow::Result { let endpoint = self .api .call(act_ok!(actor => async move { diff --git a/crates/rustpatcher/src/embed.rs b/crates/rustpatcher/src/embed.rs index 93e3efd..2c32a34 100644 --- a/crates/rustpatcher/src/embed.rs +++ b/crates/rustpatcher/src/embed.rs @@ -77,7 +77,10 @@ const _: () = { #[cfg_attr(target_os = "macos", unsafe(link_section = "__DATA,__embsig"))] #[cfg_attr(target_os = "linux", unsafe(link_section = ".embsig"))] #[cfg_attr(target_os = "windows", unsafe(link_section = ".embsig"))] -#[cfg_attr(not(any(target_os = "macos", target_os = "linux", target_os = "windows")), unsafe(link_section = ".embsig"))] +#[cfg_attr( + not(any(target_os = "macos", target_os = "linux", target_os = "windows")), + unsafe(link_section = ".embsig") +)] #[used] #[unsafe(no_mangle)] pub static EMBED_REGION: [u8; EMBED_REGION_LEN] = { diff --git a/crates/rustpatcher/src/macho.rs b/crates/rustpatcher/src/macho.rs index 68299f0..08cc2dc 100644 --- a/crates/rustpatcher/src/macho.rs +++ b/crates/rustpatcher/src/macho.rs @@ -1,4 +1,4 @@ -use anyhow::{anyhow, Result}; +use anyhow::{Result, anyhow}; use goblin::mach::{Mach, MachO}; pub fn exclude_code_signature(data: &[u8]) -> Result> { @@ -18,7 +18,8 @@ fn exclude_from_macho(data: &[u8], macho: &MachO) -> Result> { if offset > data.len() { return Err(anyhow!( "Code signature offset out of bounds: offset={}, file_len={}", - offset, data.len() + offset, + data.len() )); } @@ -31,4 +32,4 @@ fn exclude_from_macho(data: &[u8], macho: &MachO) -> Result> { // No code signature found, return original Ok(data.to_vec()) -} \ No newline at end of file +} diff --git a/crates/rustpatcher/src/patch.rs b/crates/rustpatcher/src/patch.rs index 79056da..6b80bb6 100644 --- a/crates/rustpatcher/src/patch.rs +++ b/crates/rustpatcher/src/patch.rs @@ -59,11 +59,7 @@ impl Patch { Ok(()) } - pub fn sign( - owner_signing_key: SigningKey, - data: &[u8], - ) -> anyhow::Result { - + pub fn sign(owner_signing_key: SigningKey, data: &[u8]) -> anyhow::Result { #[cfg(target_os = "macos")] let data_stripped = crate::macho::exclude_code_signature(data)?; #[cfg(target_os = "macos")] @@ -71,8 +67,7 @@ impl Patch { #[cfg(not(target_os = "macos"))] let data_stripped = data; - let (data_no_embed, data_embed, _) = - crate::embed::cut_embed_section(data_stripped)?; + let (data_no_embed, data_embed, _) = crate::embed::cut_embed_section(data_stripped)?; let version = crate::embed::get_embedded_version(&data_embed)?; let mut data_hasher = sha2::Sha512::new(); diff --git a/crates/rustpatcher/src/publisher.rs b/crates/rustpatcher/src/publisher.rs index c5904cc..b33eed9 100644 --- a/crates/rustpatcher/src/publisher.rs +++ b/crates/rustpatcher/src/publisher.rs @@ -1,4 +1,4 @@ -use actor_helper::{act_ok, Action, Actor, Handle, Receiver}; +use actor_helper::{Action, Actor, Handle, Receiver, act_ok}; use distributed_topic_tracker::{RecordPublisher, unix_minute}; use iroh::EndpointId; use tracing::{debug, error, warn}; diff --git a/crates/rustpatcher/xtask/sign.rs b/crates/rustpatcher/xtask/sign.rs index 36b5751..2b8989f 100644 --- a/crates/rustpatcher/xtask/sign.rs +++ b/crates/rustpatcher/xtask/sign.rs @@ -103,10 +103,10 @@ fn sign_cmd(args: SignArgs) -> anyhow::Result<()> { .open(&args.binary)?; let mut data = fs::read(&args.binary) - .map_err(|e| anyhow::anyhow!("failed to read binary {}: {}", args.binary.display(), e))?; + .map_err(|e| anyhow::anyhow!("failed to read binary {}: {}", args.binary.display(), e))?; let patch_info = rustpatcher::Patch::sign(signing_key, data.as_slice())?; - let (_,_,embed_region) = rustpatcher::embed::cut_embed_section(data.as_slice())?; + let (_, _, embed_region) = rustpatcher::embed::cut_embed_section(data.as_slice())?; rustpatcher::embed::set_embedded_patch_info(&mut data, patch_info, embed_region)?; file.seek(SeekFrom::Start(0))?; @@ -123,7 +123,6 @@ fn sign_cmd(args: SignArgs) -> anyhow::Result<()> { #[cfg(target_os = "macos")] fn macos_codesign(binary: &PathBuf) -> anyhow::Result<()> { - // re-sign the binary with codesign let status = std::process::Command::new("codesign") .arg("--force")