diff --git a/kinode/packages/kns_indexer/kns_indexer/src/lib.rs b/kinode/packages/kns_indexer/kns_indexer/src/lib.rs index 21447a8fd..5921fd27d 100644 --- a/kinode/packages/kns_indexer/kns_indexer/src/lib.rs +++ b/kinode/packages/kns_indexer/kns_indexer/src/lib.rs @@ -311,7 +311,7 @@ fn handle_log(our: &Address, state: &mut State, log: ð::Log) -> anyhow::Resul }; state.names.insert(child_hash.clone(), full_name.clone()); - println!("inserted child hash: {child_hash}, with full name: {full_name}"); + // println!("inserted child hash: {child_hash}, with full name: {full_name}"); state.nodes.insert( full_name.clone(), net::KnsUpdate { @@ -360,7 +360,7 @@ fn handle_log(our: &Address, state: &mut State, log: ð::Log) -> anyhow::Resul } } "~routers" => { - let routers = decode_routers(&decoded.data)?; + let routers = decode_routers(&decoded.data, &state)?; if let Some(node) = state.nodes.get_mut(&node_name) { node.routers = routers; // -> indirect @@ -482,24 +482,39 @@ fn add_temp_hardcoded_tlzs(state: &mut State) { ); } -/// Decodes bytes into an array of node identities, expecting UTF-8 encoded strings separated by newlines. -fn decode_routers(data: &[u8]) -> anyhow::Result> { - let data_str = std::str::from_utf8(data)?; - let routers = data_str.split(',').map(str::to_owned).collect(); +/// Decodes bytes into an array of keccak256 hashes (32 bytes each) and returns their full names. +fn decode_routers(data: &[u8], state: &State) -> anyhow::Result> { + if data.len() % 32 != 0 { + return Err(anyhow::anyhow!("got invalid data length for router hashes")); + } + + let mut routers = Vec::new(); + for chunk in data.chunks(32) { + let hash_str = format!("0x{}", hex::encode(chunk)); + + match state.names.get(&hash_str) { + Some(full_name) => routers.push(full_name.clone()), + None => print_to_terminal( + 1, + &format!("error: no name found for router hash {hash_str}"), + ), + } + } + Ok(routers) } pub fn bytes_to_ip(bytes: &[u8]) -> anyhow::Result { match bytes.len() { + 4 => { + // IPv4 address + let ip_num = u32::from_be_bytes(bytes.try_into().unwrap()); + Ok(IpAddr::V4(Ipv4Addr::from(ip_num))) + } 16 => { + // IPv6 address let ip_num = u128::from_be_bytes(bytes.try_into().unwrap()); - if ip_num < (1u128 << 32) { - // IPv4 - Ok(IpAddr::V4(Ipv4Addr::from(ip_num as u32))) - } else { - // IPv6 - Ok(IpAddr::V6(Ipv6Addr::from(ip_num))) - } + Ok(IpAddr::V6(Ipv6Addr::from(ip_num))) } _ => Err(anyhow::anyhow!("Invalid byte length for IP address")), } diff --git a/kinode/src/keygen.rs b/kinode/src/keygen.rs index fbbd39946..1b05f6f6e 100644 --- a/kinode/src/keygen.rs +++ b/kinode/src/keygen.rs @@ -161,31 +161,35 @@ pub fn namehash(name: &str) -> [u8; 32] { node.into() } -pub fn bytes_to_ip(bytes: &[u8]) -> Result { +pub fn bytes_to_ip(bytes: &[u8]) -> Result { match bytes.len() { + 4 => { + // IPv4 address + let ip_num = u32::from_be_bytes(bytes.try_into().unwrap()); + Ok(IpAddr::V4(Ipv4Addr::from(ip_num))) + } 16 => { + // IPv6 address let ip_num = u128::from_be_bytes(bytes.try_into().unwrap()); - if ip_num < (1u128 << 32) { - // IPv4 - Ok(IpAddr::V4(Ipv4Addr::from(ip_num as u32))) - } else { - // IPv6 - Ok(IpAddr::V6(Ipv6Addr::from(ip_num))) - } + Ok(IpAddr::V6(Ipv6Addr::from(ip_num))) } - other => Err(format!("Invalid byte length for IP address: {other}")), + _ => Err(anyhow::anyhow!("Invalid byte length for IP address")), } } #[cfg(feature = "simulation-mode")] -pub fn ip_to_bytes(ip: IpAddr) -> [u8; 16] { +pub fn ip_to_bytes(ip: IpAddr) -> Vec { match ip { IpAddr::V4(ipv4) => { - let mut bytes = [0u8; 16]; - bytes[12..].copy_from_slice(&ipv4.octets()); + let mut bytes = Vec::with_capacity(4); + bytes.extend_from_slice(&ipv4.octets()); + bytes + } + IpAddr::V6(ipv6) => { + let mut bytes = Vec::with_capacity(16); + bytes.extend_from_slice(&ipv6.octets()); bytes } - IpAddr::V6(ipv6) => ipv6.octets(), } } diff --git a/kinode/src/register-ui/src/abis/helpers.ts b/kinode/src/register-ui/src/abis/helpers.ts index 9ee216b29..8cae088f2 100644 --- a/kinode/src/register-ui/src/abis/helpers.ts +++ b/kinode/src/register-ui/src/abis/helpers.ts @@ -1,9 +1,17 @@ import { NetworkingInfo } from "../lib/types"; +import { kinohash } from "../utils/kinohash"; import { ipToBytes, portToBytes } from "../utils/kns_encoding"; import { multicallAbi, kinomapAbi, mechAbi, KINOMAP, MULTICALL } from "./"; import { encodeFunctionData, encodePacked, stringToHex, bytesToHex } from "viem"; +// Function to encode router names into keccak256 hashes +// Function to encode router names into keccak256 hashes +const encodeRouters = (routers: string[]): `0x${string}` => { + const hashedRouters = routers.map(router => kinohash(router).slice(2)); // Remove '0x' prefix + return `0x${hashedRouters.join('')}`; +}; + export const generateNetworkingKeys = async ({ direct, label, @@ -78,6 +86,8 @@ export const generateNetworkingKeys = async ({ ] }); + const encodedRouters = encodeRouters(allowed_routers); + const router_call = encodeFunctionData({ abi: kinomapAbi, @@ -86,7 +96,7 @@ export const generateNetworkingKeys = async ({ encodePacked(["bytes"], [stringToHex("~routers")]), encodePacked( ["bytes"], - [stringToHex(allowed_routers.join(","))] + [encodedRouters] )] }); diff --git a/kinode/src/register-ui/src/utils/kns_encoding.ts b/kinode/src/register-ui/src/utils/kns_encoding.ts index 83093ede6..265b2cb5a 100644 --- a/kinode/src/register-ui/src/utils/kns_encoding.ts +++ b/kinode/src/register-ui/src/utils/kns_encoding.ts @@ -20,24 +20,24 @@ export function bytesToIp(bytes: Uint8Array): string { } export function ipToBytes(ip: string): Uint8Array { - const bytes = new Uint8Array(16); - const view = new DataView(bytes.buffer); - if (ip.includes(':')) { - // IPv6 + // IPv6: Create a 16-byte array + const bytes = new Uint8Array(16); + const view = new DataView(bytes.buffer); const parts = ip.split(':'); for (let i = 0; i < 8; i++) { view.setUint16(i * 2, parseInt(parts[i] || '0', 16)); } + return bytes; } else { - // IPv4 + // IPv4: Create a 4-byte array + const bytes = new Uint8Array(4); const parts = ip.split('.'); for (let i = 0; i < 4; i++) { - bytes[12 + i] = parseInt(parts[i], 10); + bytes[i] = parseInt(parts[i], 10); } + return bytes; } - - return bytes; } export function bytesToPort(bytes: Uint8Array): number {