From 24c5f193b9141a8028ede0791401266614d1db7d Mon Sep 17 00:00:00 2001 From: hosted-fornet Date: Thu, 13 Mar 2025 22:43:07 -0700 Subject: [PATCH 1/3] fix fake chain and short node name * short node name: we use node name for salt but minimum argon2 salt length is 8. add logic to create salt from concatenation of node name when node name is too short by itself * fake chain sister PR: https://github.com/hyperware-ai/kit/pull/299 --- Cargo.lock | 6 +++--- Cargo.toml | 2 +- hyperdrive/Cargo.toml | 2 +- .../hns-indexer/hns-indexer/src/lib.rs | 10 ++++++++++ hyperdrive/src/fakenet.rs | 11 ++++++----- hyperdrive/src/http/login.html | 12 ++++++++++-- hyperdrive/src/http/server.rs | 2 ++ hyperdrive/src/main.rs | 13 ++++++++++++- .../register-ui/src/pages/ImportKeyfile.tsx | 16 +++++++++++++++- .../src/register-ui/src/pages/Login.tsx | 12 ++++++++++-- .../src/register-ui/src/pages/SetPassword.tsx | 19 +++++++++++++++++-- lib/Cargo.toml | 2 +- 12 files changed, 88 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index efbb22c4c..f9f1deb30 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3161,7 +3161,7 @@ dependencies = [ [[package]] name = "hyperdrive" -version = "1.1.0" +version = "1.1.1" dependencies = [ "aes-gcm", "alloy", @@ -3217,7 +3217,7 @@ dependencies = [ [[package]] name = "hyperdrive_lib" -version = "1.1.0" +version = "1.1.1" dependencies = [ "lib", ] @@ -3751,7 +3751,7 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "lib" -version = "1.1.0" +version = "1.1.1" dependencies = [ "alloy", "anyhow", diff --git a/Cargo.toml b/Cargo.toml index 6ce2f10c5..e1749396c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "hyperdrive_lib" authors = ["Sybil Technologies AG"] -version = "1.1.0" +version = "1.1.1" edition = "2021" description = "A general-purpose sovereign cloud computing platform" homepage = "https://hyperware.ai" diff --git a/hyperdrive/Cargo.toml b/hyperdrive/Cargo.toml index 71138ba21..52464d7df 100644 --- a/hyperdrive/Cargo.toml +++ b/hyperdrive/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "hyperdrive" authors = ["Sybil Technologies AG"] -version = "1.1.0" +version = "1.1.1" edition = "2021" description = "A general-purpose sovereign cloud computing platform" homepage = "https://hyperware.ai" diff --git a/hyperdrive/packages/hns-indexer/hns-indexer/src/lib.rs b/hyperdrive/packages/hns-indexer/hns-indexer/src/lib.rs index 4d871d4fd..dfb8fb756 100644 --- a/hyperdrive/packages/hns-indexer/hns-indexer/src/lib.rs +++ b/hyperdrive/packages/hns-indexer/hns-indexer/src/lib.rs @@ -367,11 +367,14 @@ fn handle_eth_message( notes_filter: ð::Filter, last_block: &mut u64, ) -> anyhow::Result<()> { + print_to_terminal(0, "hem 0"); match serde_json::from_slice::(body) { Ok(Ok(eth::EthSub { result, .. })) => { + print_to_terminal(0, "hem 0"); if let Ok(eth::SubscriptionResult::Log(log)) = serde_json::from_value::(result) { + print_to_terminal(0, "hem 1"); if let Err(e) = handle_log(state, pending_notes, &log, last_block) { print_to_terminal(1, &format!("log-handling error! {e:?}")); } @@ -453,6 +456,7 @@ fn handle_pending_notes( } fn handle_note(state: &mut State, note: &hypermap::contract::Note) -> anyhow::Result<()> { + print_to_terminal(0, "hn 0"); let note_label = String::from_utf8(note.label.to_vec())?; let node_hash = note.parenthash.to_string(); @@ -463,6 +467,7 @@ fn handle_note(state: &mut State, note: &hypermap::contract::Note) -> anyhow::Re let Some(node_name) = state.names.get(&node_hash) else { return Err(HnsError::NoParentError.into()); }; + print_to_terminal(0, &format!("hn 1: {node_name} {note_label}")); match note_label.as_str() { "~ws-port" => { @@ -535,12 +540,14 @@ fn handle_log( log: ð::Log, last_block: &mut u64, ) -> anyhow::Result<()> { + print_to_terminal(0, "hl 0"); if let Some(block) = log.block_number { *last_block = block; } match log.topics()[0] { hypermap::contract::Mint::SIGNATURE_HASH => { + print_to_terminal(0, "hl mint 0"); let decoded = hypermap::contract::Mint::decode_log_data(log.data(), true).unwrap(); let parent_hash = decoded.parenthash.to_string(); let child_hash = decoded.childhash.to_string(); @@ -550,10 +557,12 @@ fn handle_log( return Err(anyhow::anyhow!("skipping invalid name: {name}")); } + print_to_terminal(0, "hl mint 1"); let full_name = match state.names.get(&parent_hash) { Some(parent_name) => format!("{name}.{parent_name}"), None => name, }; + print_to_terminal(0, &format!("hl mint 2: {full_name}")); state.names.insert(child_hash.clone(), full_name.clone()); state.nodes.insert( @@ -568,6 +577,7 @@ fn handle_log( ); } hypermap::contract::Note::SIGNATURE_HASH => { + print_to_terminal(0, "hl note 0"); let decoded = hypermap::contract::Note::decode_log_data(log.data(), true).unwrap(); let note: String = String::from_utf8(decoded.label.to_vec())?; diff --git a/hyperdrive/src/fakenet.rs b/hyperdrive/src/fakenet.rs index 759493496..594585b7b 100644 --- a/hyperdrive/src/fakenet.rs +++ b/hyperdrive/src/fakenet.rs @@ -13,8 +13,8 @@ use std::str::FromStr; use crate::{keygen, sol::*, HYPERMAP_ADDRESS, HYPER_ACCOUNT_IMPL, MULTICALL_ADDRESS}; const FAKE_DOTDEV_TBA: &str = "0xcc3A576b8cE5340f5CE23d0DDAf133C0822C3B6d"; -const FAKE_DOTOS_TBA: &str = "0xbE46837617f8304Aa5E6d0aE62B74340251f48Bf"; -const _FAKE_ZEROTH_TBA: &str = "0x4bb0778bb92564bf8e82d0b3271b7512443fb060"; +const FAKE_DOTOS_TBA: &str = "0x9b3853358ede717fc7D4806cF75d7A4d4517A9C9"; +const _FAKE_ZEROTH_TBA: &str = "0x809A598d9883f2Fb6B77382eBfC9473Fd6A857c9"; /// Attempts to connect to a local anvil fakechain, /// registering a name with its KiMap contract. @@ -45,6 +45,7 @@ pub async fn mint_local( Some(&"dev") => dotdev, _ => dotdev, }; + println!("mint_local name, tlz, addy: {name}, {:?}, {minter}", parts.get(1)); let endpoint = format!("ws://localhost:{}", fakechain_port); let ws = WsConnect::new(endpoint); @@ -64,7 +65,6 @@ pub async fn mint_local( .input(TransactionInput::new(get_call.into())); let exists = provider.call(&get_tx).await?; - println!("exists: {:?}", exists); let decoded = getCall::abi_decode_returns(&exists, false)?; @@ -73,8 +73,6 @@ pub async fn mint_local( let bytes = decoded.data; // now set ip, port and pubkey - println!("tba, owner and bytes: {:?}, {:?}, {:?}", tba, _owner, bytes); - let localhost = Ipv4Addr::new(127, 0, 0, 1); let ip = keygen::ip_to_bytes(localhost.into()); let pubkey = hex::decode(pubkey)?; @@ -112,6 +110,7 @@ pub async fn mint_local( ]; let is_reset = tba != Address::default(); + println!("is_reset, tba, owner, bytes: {}, {:?}, {:?}, {:?}", is_reset, tba, _owner, bytes); let multicall = aggregateCall { calls: multicalls }.abi_encode(); @@ -161,6 +160,8 @@ pub async fn mint_local( let tx_hash = provider.send_raw_transaction(&tx_encoded).await?; let _receipt = tx_hash.get_receipt().await?; + println!("mint receipt: {:?}", _receipt); + // send a small amount of ETH to the zero address // this is a workaround to get anvil to mine a block after our registration tx // instead of doing block-time 1s or similar, which leads to runaway mem-usage. diff --git a/hyperdrive/src/http/login.html b/hyperdrive/src/http/login.html index e171734dc..d37c6e3a8 100644 --- a/hyperdrive/src/http/login.html +++ b/hyperdrive/src/http/login.html @@ -158,9 +158,16 @@

Logging in...

document.getElementById("loading").style.display = "flex"; try { + // salt is either node name (if node name is longer than 8 characters) + // or node name repeated enough times to be longer than 8 characters + const hnsName = `${node}`; + const minSaltL = 8; + const nameL = hnsName.length; + const salt = nameL >= minSaltL ? hnsName : hnsName.repeat(1 + Math.floor(minSaltL / nameL)); + const h = await argon2.hash({ pass: password, - salt: '${node}', + salt: salt, hashLen: 32, time: 2, mem: 19456, @@ -186,6 +193,7 @@

Logging in...

throw new Error("Login failed"); } catch (err) { + console.log(`login failed with err: ${JSON.stringify(err)}`); document.getElementById("login-form").style.display = "flex"; document.getElementById("loading").style.display = "none"; document.getElementById("password").value = ""; @@ -220,4 +228,4 @@

Logging in...

- \ No newline at end of file + diff --git a/hyperdrive/src/http/server.rs b/hyperdrive/src/http/server.rs index f6703b5f5..d6ec42693 100644 --- a/hyperdrive/src/http/server.rs +++ b/hyperdrive/src/http/server.rs @@ -341,6 +341,8 @@ async fn login_handler( subdomain: info.subdomain, }; + println!("login_handler: got info {info:?}\r"); + match keygen::decode_keyfile(&encoded_keyfile, &info.password_hash) { Ok(keyfile) => { let token = match keygen::generate_jwt( diff --git a/hyperdrive/src/main.rs b/hyperdrive/src/main.rs index 24b376156..a72c0d747 100644 --- a/hyperdrive/src/main.rs +++ b/hyperdrive/src/main.rs @@ -654,6 +654,7 @@ pub async fn simulate_node( } Some(name) => { let password_hash = password.unwrap_or_else(|| "secret".to_string()); + println!("main: password_hash: {password_hash}\r"); let (pubkey, networking_keypair) = keygen::generate_networking_key(); let seed = SystemRandom::new(); let mut jwt_secret = [0u8; 32]; @@ -902,11 +903,21 @@ async fn login_with_password( }) .unwrap(); + // salt is either node name (if node name is longer than 8 characters) + // or node name repeated enough times to be longer than 8 characters + let min_salt_len = 8; + let name_len = username.len(); + let salt = if name_len >= min_salt_len { + username + } else { + username.repeat(1 + min_salt_len / name_len) + }; + let mut output_key_material = [0u8; 32]; Argon2::default() .hash_password_into( password.as_bytes(), - username.as_bytes(), + salt.as_bytes(), &mut output_key_material, ) .expect("password hashing failed"); diff --git a/hyperdrive/src/register-ui/src/pages/ImportKeyfile.tsx b/hyperdrive/src/register-ui/src/pages/ImportKeyfile.tsx index f471ddaf9..c035f3f70 100644 --- a/hyperdrive/src/register-ui/src/pages/ImportKeyfile.tsx +++ b/hyperdrive/src/register-ui/src/pages/ImportKeyfile.tsx @@ -55,7 +55,21 @@ function ImportKeyfile({ try { if (keyErrs.length === 0 && localKey !== null) { - argon2.hash({ pass: pw, salt: hnsName, hashLen: 32, time: 2, mem: 19456, type: argon2.ArgonType.Argon2id }).then(async h => { + // salt is either node name (if node name is longer than 8 characters) + // or node name repeated enough times to be longer than 8 characters + const minSaltL = 8; + const nodeL = hnsName.length; + const salt = nodeL >= minSaltL ? hnsName : hnsName.repeat(1 + Math.floor(minSaltL / nodeL)); + console.log(salt); + + argon2.hash({ + pass: pw, + salt: salt, + hashLen: 32, + time: 2, + mem: 19456, + type: argon2.ArgonType.Argon2id + }).then(async h => { const hashed_password_hex = `0x${h.hashHex}`; const result = await fetch("/import-keyfile", { diff --git a/hyperdrive/src/register-ui/src/pages/Login.tsx b/hyperdrive/src/register-ui/src/pages/Login.tsx index 2ad2dfbb5..08a9c294a 100644 --- a/hyperdrive/src/register-ui/src/pages/Login.tsx +++ b/hyperdrive/src/register-ui/src/pages/Login.tsx @@ -45,9 +45,17 @@ function Login({ try { // Try argon2 hash first + + // salt is either node name (if node name is longer than 8 characters) + // or node name repeated enough times to be longer than 8 characters + const minSaltL = 8; + const nodeL = hnsName.length; + const salt = nodeL >= minSaltL ? hnsName : hnsName.repeat(1 + Math.floor(minSaltL / nodeL)); + console.log(salt); + const h = await argon2.hash({ pass: pw, - salt: hnsName, + salt: salt, hashLen: 32, time: 2, mem: 19456, @@ -136,4 +144,4 @@ function Login({ ); } -export default Login; \ No newline at end of file +export default Login; diff --git a/hyperdrive/src/register-ui/src/pages/SetPassword.tsx b/hyperdrive/src/register-ui/src/pages/SetPassword.tsx index 2d7c4296f..c0b35ceda 100644 --- a/hyperdrive/src/register-ui/src/pages/SetPassword.tsx +++ b/hyperdrive/src/register-ui/src/pages/SetPassword.tsx @@ -50,7 +50,22 @@ function SetPassword({ setTimeout(async () => { setLoading(true); - argon2.hash({ pass: pw, salt: hnsName, hashLen: 32, time: 2, mem: 19456, type: argon2.ArgonType.Argon2id }).then(async h => { + + // salt is either node name (if node name is longer than 8 characters) + // or node name repeated enough times to be longer than 8 characters + const minSaltL = 8; + const nodeL = hnsName.length; + const salt = nodeL >= minSaltL ? hnsName : hnsName.repeat(1 + Math.floor(minSaltL / nodeL)); + console.log(salt); + + argon2.hash({ + pass: pw, + salt: salt, + hashLen: 32, + time: 2, + mem: 19456, + type: argon2.ArgonType.Argon2id + }).then(async h => { const hashed_password_hex = `0x${h.hashHex}` as `0x${string}`; let owner = address; let timestamp = Date.now(); @@ -160,4 +175,4 @@ function SetPassword({ ); } -export default SetPassword; \ No newline at end of file +export default SetPassword; diff --git a/lib/Cargo.toml b/lib/Cargo.toml index 1d79ac4f3..083175a0b 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "lib" authors = ["Sybil Technologies AG"] -version = "1.1.0" +version = "1.1.1" edition = "2021" description = "A general-purpose sovereign cloud computing platform" homepage = "https://hyperware.ai" From 6a4e9b5e6e7f02bed92b4a9014585ae7a1d78d0f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 14 Mar 2025 05:45:29 +0000 Subject: [PATCH 2/3] Format Rust code using rustfmt --- hyperdrive/src/fakenet.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/hyperdrive/src/fakenet.rs b/hyperdrive/src/fakenet.rs index 594585b7b..837ec87ec 100644 --- a/hyperdrive/src/fakenet.rs +++ b/hyperdrive/src/fakenet.rs @@ -45,7 +45,10 @@ pub async fn mint_local( Some(&"dev") => dotdev, _ => dotdev, }; - println!("mint_local name, tlz, addy: {name}, {:?}, {minter}", parts.get(1)); + println!( + "mint_local name, tlz, addy: {name}, {:?}, {minter}", + parts.get(1) + ); let endpoint = format!("ws://localhost:{}", fakechain_port); let ws = WsConnect::new(endpoint); @@ -110,7 +113,10 @@ pub async fn mint_local( ]; let is_reset = tba != Address::default(); - println!("is_reset, tba, owner, bytes: {}, {:?}, {:?}, {:?}", is_reset, tba, _owner, bytes); + println!( + "is_reset, tba, owner, bytes: {}, {:?}, {:?}, {:?}", + is_reset, tba, _owner, bytes + ); let multicall = aggregateCall { calls: multicalls }.abi_encode(); From bd9e5bd5a51a521fff434727c63fcaee525c27d9 Mon Sep 17 00:00:00 2001 From: hosted-fornet Date: Fri, 14 Mar 2025 06:21:14 -0700 Subject: [PATCH 3/3] cleanup fakenet and remove some debugging prints --- .../packages/hns-indexer/hns-indexer/src/lib.rs | 16 ++-------------- hyperdrive/src/fakenet.rs | 13 ++----------- hyperdrive/src/main.rs | 1 - 3 files changed, 4 insertions(+), 26 deletions(-) diff --git a/hyperdrive/packages/hns-indexer/hns-indexer/src/lib.rs b/hyperdrive/packages/hns-indexer/hns-indexer/src/lib.rs index dfb8fb756..225ab3981 100644 --- a/hyperdrive/packages/hns-indexer/hns-indexer/src/lib.rs +++ b/hyperdrive/packages/hns-indexer/hns-indexer/src/lib.rs @@ -367,14 +367,11 @@ fn handle_eth_message( notes_filter: ð::Filter, last_block: &mut u64, ) -> anyhow::Result<()> { - print_to_terminal(0, "hem 0"); match serde_json::from_slice::(body) { Ok(Ok(eth::EthSub { result, .. })) => { - print_to_terminal(0, "hem 0"); if let Ok(eth::SubscriptionResult::Log(log)) = serde_json::from_value::(result) { - print_to_terminal(0, "hem 1"); if let Err(e) = handle_log(state, pending_notes, &log, last_block) { print_to_terminal(1, &format!("log-handling error! {e:?}")); } @@ -456,7 +453,6 @@ fn handle_pending_notes( } fn handle_note(state: &mut State, note: &hypermap::contract::Note) -> anyhow::Result<()> { - print_to_terminal(0, "hn 0"); let note_label = String::from_utf8(note.label.to_vec())?; let node_hash = note.parenthash.to_string(); @@ -467,7 +463,7 @@ fn handle_note(state: &mut State, note: &hypermap::contract::Note) -> anyhow::Re let Some(node_name) = state.names.get(&node_hash) else { return Err(HnsError::NoParentError.into()); }; - print_to_terminal(0, &format!("hn 1: {node_name} {note_label}")); + print_to_terminal(3, &format!("note {node_name}: {note_label}")); match note_label.as_str() { "~ws-port" => { @@ -540,14 +536,12 @@ fn handle_log( log: ð::Log, last_block: &mut u64, ) -> anyhow::Result<()> { - print_to_terminal(0, "hl 0"); if let Some(block) = log.block_number { *last_block = block; } match log.topics()[0] { hypermap::contract::Mint::SIGNATURE_HASH => { - print_to_terminal(0, "hl mint 0"); let decoded = hypermap::contract::Mint::decode_log_data(log.data(), true).unwrap(); let parent_hash = decoded.parenthash.to_string(); let child_hash = decoded.childhash.to_string(); @@ -557,12 +551,11 @@ fn handle_log( return Err(anyhow::anyhow!("skipping invalid name: {name}")); } - print_to_terminal(0, "hl mint 1"); let full_name = match state.names.get(&parent_hash) { Some(parent_name) => format!("{name}.{parent_name}"), None => name, }; - print_to_terminal(0, &format!("hl mint 2: {full_name}")); + print_to_terminal(3, &format!("mint {full_name}")); state.names.insert(child_hash.clone(), full_name.clone()); state.nodes.insert( @@ -577,7 +570,6 @@ fn handle_log( ); } hypermap::contract::Note::SIGNATURE_HASH => { - print_to_terminal(0, "hl note 0"); let decoded = hypermap::contract::Note::decode_log_data(log.data(), true).unwrap(); let note: String = String::from_utf8(decoded.label.to_vec())?; @@ -588,10 +580,6 @@ fn handle_log( if let Err(e) = handle_note(state, &decoded) { if let Some(HnsError::NoParentError) = e.downcast_ref::() { if let Some(block_number) = log.block_number { - // print_to_terminal( - // 1, - // &format!("adding note to pending_notes for block {block_number}"), - // ); pending_notes .entry(block_number) .or_default() diff --git a/hyperdrive/src/fakenet.rs b/hyperdrive/src/fakenet.rs index 837ec87ec..29f8ef79b 100644 --- a/hyperdrive/src/fakenet.rs +++ b/hyperdrive/src/fakenet.rs @@ -12,7 +12,6 @@ use std::str::FromStr; use crate::{keygen, sol::*, HYPERMAP_ADDRESS, HYPER_ACCOUNT_IMPL, MULTICALL_ADDRESS}; -const FAKE_DOTDEV_TBA: &str = "0xcc3A576b8cE5340f5CE23d0DDAf133C0822C3B6d"; const FAKE_DOTOS_TBA: &str = "0x9b3853358ede717fc7D4806cF75d7A4d4517A9C9"; const _FAKE_ZEROTH_TBA: &str = "0x809A598d9883f2Fb6B77382eBfC9473Fd6A857c9"; @@ -35,18 +34,16 @@ pub async fn mint_local( let multicall_address = Address::from_str(MULTICALL_ADDRESS)?; let dotos = Address::from_str(FAKE_DOTOS_TBA)?; - let dotdev = Address::from_str(FAKE_DOTDEV_TBA)?; let hypermap = Address::from_str(HYPERMAP_ADDRESS)?; let parts: Vec<&str> = name.split('.').collect(); let label = parts[0]; let minter = match parts.get(1) { Some(&"os") => dotos, - Some(&"dev") => dotdev, - _ => dotdev, + _ => dotos, }; println!( - "mint_local name, tlz, addy: {name}, {:?}, {minter}", + "mint_local name, tlz, tlz address: {name}, {:?}, {minter}", parts.get(1) ); @@ -113,10 +110,6 @@ pub async fn mint_local( ]; let is_reset = tba != Address::default(); - println!( - "is_reset, tba, owner, bytes: {}, {:?}, {:?}, {:?}", - is_reset, tba, _owner, bytes - ); let multicall = aggregateCall { calls: multicalls }.abi_encode(); @@ -166,8 +159,6 @@ pub async fn mint_local( let tx_hash = provider.send_raw_transaction(&tx_encoded).await?; let _receipt = tx_hash.get_receipt().await?; - println!("mint receipt: {:?}", _receipt); - // send a small amount of ETH to the zero address // this is a workaround to get anvil to mine a block after our registration tx // instead of doing block-time 1s or similar, which leads to runaway mem-usage. diff --git a/hyperdrive/src/main.rs b/hyperdrive/src/main.rs index a72c0d747..3c02dcc3c 100644 --- a/hyperdrive/src/main.rs +++ b/hyperdrive/src/main.rs @@ -654,7 +654,6 @@ pub async fn simulate_node( } Some(name) => { let password_hash = password.unwrap_or_else(|| "secret".to_string()); - println!("main: password_hash: {password_hash}\r"); let (pubkey, networking_keypair) = keygen::generate_networking_key(); let seed = SystemRandom::new(); let mut jwt_secret = [0u8; 32];