mirror of
https://github.com/uqbar-dao/nectar.git
synced 2025-01-03 14:17:20 +03:00
Merge pull request #282 from kinode-dao/dr/add-ws-routing-flag-and-enforce
fix: enforce ws-routing port
This commit is contained in:
commit
aa46605596
6
Cargo.lock
generated
6
Cargo.lock
generated
@ -2572,7 +2572,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kinode"
|
name = "kinode"
|
||||||
version = "0.6.1"
|
version = "0.6.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes-gcm",
|
"aes-gcm",
|
||||||
"alloy-primitives",
|
"alloy-primitives",
|
||||||
@ -2645,7 +2645,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kinode_lib"
|
name = "kinode_lib"
|
||||||
version = "0.6.1"
|
version = "0.6.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lib",
|
"lib",
|
||||||
]
|
]
|
||||||
@ -2738,7 +2738,7 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lib"
|
name = "lib"
|
||||||
version = "0.6.1"
|
version = "0.6.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"alloy-rpc-types",
|
"alloy-rpc-types",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "kinode_lib"
|
name = "kinode_lib"
|
||||||
authors = ["KinodeDAO"]
|
authors = ["KinodeDAO"]
|
||||||
version = "0.6.1"
|
version = "0.6.2"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "A general-purpose sovereign cloud computing platform"
|
description = "A general-purpose sovereign cloud computing platform"
|
||||||
homepage = "https://kinode.org"
|
homepage = "https://kinode.org"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "kinode"
|
name = "kinode"
|
||||||
authors = ["KinodeDAO"]
|
authors = ["KinodeDAO"]
|
||||||
version = "0.6.1"
|
version = "0.6.2"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "A general-purpose sovereign cloud computing platform"
|
description = "A general-purpose sovereign cloud computing platform"
|
||||||
homepage = "https://kinode.org"
|
homepage = "https://kinode.org"
|
||||||
|
@ -251,7 +251,7 @@ async fn handle_network_error(
|
|||||||
// if we hold active subscriptions for the remote node that this error refers to,
|
// if we hold active subscriptions for the remote node that this error refers to,
|
||||||
// close them here -- they will need to resubscribe
|
// close them here -- they will need to resubscribe
|
||||||
// TODO is this necessary?
|
// TODO is this necessary?
|
||||||
if let Some(sub_map) = active_subscriptions.get(&wrapped_error.error.target) {
|
if let Some((_who, sub_map)) = active_subscriptions.remove(&wrapped_error.error.target) {
|
||||||
for (_sub_id, sub) in sub_map.iter() {
|
for (_sub_id, sub) in sub_map.iter() {
|
||||||
if let ActiveSub::Local(handle) = sub {
|
if let ActiveSub::Local(handle) = sub {
|
||||||
verbose_print(
|
verbose_print(
|
||||||
|
@ -100,18 +100,18 @@ pub fn deserialize_headers(hashmap: HashMap<String, String>) -> HeaderMap {
|
|||||||
header_map
|
header_map
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn find_open_port(start_at: u16, end_at: u16) -> Option<u16> {
|
pub async fn find_open_port(start_at: u16, end_at: u16) -> Option<TcpListener> {
|
||||||
for port in start_at..end_at {
|
for port in start_at..end_at {
|
||||||
let bind_addr = format!("0.0.0.0:{}", port);
|
let bind_addr = format!("0.0.0.0:{}", port);
|
||||||
if is_port_available(&bind_addr).await {
|
if let Some(bound) = is_port_available(&bind_addr).await {
|
||||||
return Some(port);
|
return Some(bound);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn is_port_available(bind_addr: &str) -> bool {
|
pub async fn is_port_available(bind_addr: &str) -> Option<TcpListener> {
|
||||||
TcpListener::bind(bind_addr).await.is_ok()
|
TcpListener::bind(bind_addr).await.ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _binary_encoded_string_to_bytes(s: &str) -> Vec<u8> {
|
pub fn _binary_encoded_string_to_bytes(s: &str) -> Vec<u8> {
|
||||||
|
@ -44,6 +44,7 @@ const DEFAULT_PROVIDERS_MAINNET: &str = include_str!("eth/default_providers_main
|
|||||||
async fn serve_register_fe(
|
async fn serve_register_fe(
|
||||||
home_directory_path: &str,
|
home_directory_path: &str,
|
||||||
our_ip: String,
|
our_ip: String,
|
||||||
|
ws_networking: (tokio::net::TcpListener, bool),
|
||||||
http_server_port: u16,
|
http_server_port: u16,
|
||||||
testnet: bool,
|
testnet: bool,
|
||||||
) -> (Identity, Vec<u8>, Keyfile) {
|
) -> (Identity, Vec<u8>, Keyfile) {
|
||||||
@ -66,7 +67,7 @@ async fn serve_register_fe(
|
|||||||
|
|
||||||
let (tx, mut rx) = mpsc::channel::<(Identity, Keyfile, Vec<u8>)>(1);
|
let (tx, mut rx) = mpsc::channel::<(Identity, Keyfile, Vec<u8>)>(1);
|
||||||
let (our, decoded_keyfile, encoded_keyfile) = tokio::select! {
|
let (our, decoded_keyfile, encoded_keyfile) = tokio::select! {
|
||||||
_ = register::register(tx, kill_rx, our_ip, http_server_port, disk_keyfile, testnet) => {
|
_ = register::register(tx, kill_rx, our_ip, ws_networking, http_server_port, disk_keyfile, testnet) => {
|
||||||
panic!("registration failed")
|
panic!("registration failed")
|
||||||
}
|
}
|
||||||
Some((our, decoded_keyfile, encoded_keyfile)) = rx.recv() => {
|
Some((our, decoded_keyfile, encoded_keyfile)) = rx.recv() => {
|
||||||
@ -97,6 +98,11 @@ async fn main() {
|
|||||||
arg!(--port <PORT> "Port to bind [default: first unbound at or above 8080]")
|
arg!(--port <PORT> "Port to bind [default: first unbound at or above 8080]")
|
||||||
.value_parser(value_parser!(u16)),
|
.value_parser(value_parser!(u16)),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
arg!(--"ws-port" <PORT> "Kinode internal WebSockets protocol port [default: first unbound at or above 9000]")
|
||||||
|
.alias("network-router-port")
|
||||||
|
.value_parser(value_parser!(u16)),
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
arg!(--testnet "If set, use Sepolia testnet")
|
arg!(--testnet "If set, use Sepolia testnet")
|
||||||
.default_value("false")
|
.default_value("false")
|
||||||
@ -118,11 +124,6 @@ async fn main() {
|
|||||||
let app = app
|
let app = app
|
||||||
.arg(arg!(--password <PASSWORD> "Networking password"))
|
.arg(arg!(--password <PASSWORD> "Networking password"))
|
||||||
.arg(arg!(--"fake-node-name" <NAME> "Name of fake node to boot"))
|
.arg(arg!(--"fake-node-name" <NAME> "Name of fake node to boot"))
|
||||||
.arg(
|
|
||||||
arg!(--"network-router-port" <PORT> "Network router port")
|
|
||||||
.default_value("9001")
|
|
||||||
.value_parser(value_parser!(u16)),
|
|
||||||
)
|
|
||||||
.arg(
|
.arg(
|
||||||
arg!(--detached <IS_DETACHED> "Run in detached mode (don't accept input)")
|
arg!(--detached <IS_DETACHED> "Run in detached mode (don't accept input)")
|
||||||
.action(clap::ArgAction::SetTrue),
|
.action(clap::ArgAction::SetTrue),
|
||||||
@ -131,21 +132,16 @@ async fn main() {
|
|||||||
let matches = app.get_matches();
|
let matches = app.get_matches();
|
||||||
|
|
||||||
let home_directory_path = matches.get_one::<String>("home").unwrap();
|
let home_directory_path = matches.get_one::<String>("home").unwrap();
|
||||||
let (port, port_flag_used) = match matches.get_one::<u16>("port") {
|
|
||||||
Some(port) => (*port, true),
|
|
||||||
None => (8080, false),
|
|
||||||
};
|
|
||||||
let on_testnet = *matches.get_one::<bool>("testnet").unwrap();
|
let on_testnet = *matches.get_one::<bool>("testnet").unwrap();
|
||||||
|
|
||||||
|
let http_port = matches.get_one::<u16>("port");
|
||||||
|
let ws_networking_port = matches.get_one::<u16>("ws-port");
|
||||||
|
|
||||||
#[cfg(not(feature = "simulation-mode"))]
|
#[cfg(not(feature = "simulation-mode"))]
|
||||||
let is_detached = false;
|
let is_detached = false;
|
||||||
#[cfg(feature = "simulation-mode")]
|
#[cfg(feature = "simulation-mode")]
|
||||||
let (password, network_router_port, fake_node_name, is_detached) = (
|
let (password, fake_node_name, is_detached) = (
|
||||||
matches.get_one::<String>("password"),
|
matches.get_one::<String>("password"),
|
||||||
matches
|
|
||||||
.get_one::<u16>("network-router-port")
|
|
||||||
.unwrap()
|
|
||||||
.clone(),
|
|
||||||
matches.get_one::<String>("fake-node-name"),
|
matches.get_one::<String>("fake-node-name"),
|
||||||
*matches.get_one::<bool>("detached").unwrap(),
|
*matches.get_one::<bool>("detached").unwrap(),
|
||||||
);
|
);
|
||||||
@ -262,35 +258,59 @@ async fn main() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let http_server_port = if port_flag_used {
|
let http_server_port = if let Some(port) = http_port {
|
||||||
match http::utils::find_open_port(port, port + 1).await {
|
match http::utils::find_open_port(*port, port + 1).await {
|
||||||
Some(port) => port,
|
Some(bound) => bound.local_addr().unwrap().port(),
|
||||||
None => {
|
None => {
|
||||||
println!(
|
println!(
|
||||||
"error: couldn't bind {}; first available port found was {}. \
|
"error: couldn't bind {}; first available port found was {}. \
|
||||||
Set an available port with `--port` and try again.",
|
Set an available port with `--port` and try again.",
|
||||||
port,
|
port,
|
||||||
http::utils::find_open_port(port, port + 1000)
|
http::utils::find_open_port(*port, port + 1000)
|
||||||
.await
|
.await
|
||||||
.expect("no ports found in range"),
|
.expect("no ports found in range")
|
||||||
|
.local_addr()
|
||||||
|
.unwrap()
|
||||||
|
.port(),
|
||||||
);
|
);
|
||||||
panic!();
|
panic!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match http::utils::find_open_port(port, port + 1000).await {
|
match http::utils::find_open_port(8080, 8999).await {
|
||||||
Some(port) => port,
|
Some(bound) => bound.local_addr().unwrap().port(),
|
||||||
None => {
|
None => {
|
||||||
println!(
|
println!(
|
||||||
"error: couldn't bind any ports between {port} and {}. \
|
"error: couldn't bind any ports between 8080 and 8999. \
|
||||||
Set an available port with `--port` and try again.",
|
Set an available port with `--port` and try again."
|
||||||
port + 1000,
|
|
||||||
);
|
);
|
||||||
panic!();
|
panic!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// if the --ws-port flag is used, bind to that port right away.
|
||||||
|
// if the flag is not used, find the first available port between 9000 and 65535.
|
||||||
|
// NOTE: if the node has a different port specified in its onchain (direct) id,
|
||||||
|
// booting will fail if the flag was used to select a different port.
|
||||||
|
// if the flag was not used, the bound port will be dropped in favor of the onchain port.
|
||||||
|
|
||||||
|
let (ws_tcp_handle, flag_used) = if let Some(port) = ws_networking_port {
|
||||||
|
(
|
||||||
|
http::utils::find_open_port(*port, port + 1)
|
||||||
|
.await
|
||||||
|
.expect("ws-port selected with flag could not be bound"),
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
http::utils::find_open_port(9000, 65535)
|
||||||
|
.await
|
||||||
|
.expect("no ports found in range 9000-65535 for websocket server"),
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
"login or register at http://localhost:{}\r",
|
"login or register at http://localhost:{}\r",
|
||||||
http_server_port
|
http_server_port
|
||||||
@ -300,6 +320,7 @@ async fn main() {
|
|||||||
let (our, encoded_keyfile, decoded_keyfile) = serve_register_fe(
|
let (our, encoded_keyfile, decoded_keyfile) = serve_register_fe(
|
||||||
home_directory_path,
|
home_directory_path,
|
||||||
our_ip.to_string(),
|
our_ip.to_string(),
|
||||||
|
(ws_tcp_handle, flag_used),
|
||||||
http_server_port,
|
http_server_port,
|
||||||
on_testnet, // true if testnet mode
|
on_testnet, // true if testnet mode
|
||||||
)
|
)
|
||||||
@ -313,7 +334,8 @@ async fn main() {
|
|||||||
serve_register_fe(
|
serve_register_fe(
|
||||||
&home_directory_path,
|
&home_directory_path,
|
||||||
our_ip.to_string(),
|
our_ip.to_string(),
|
||||||
http_server_port.clone(),
|
(ws_tcp_handle, flag_used),
|
||||||
|
http_server_port,
|
||||||
on_testnet, // true if testnet mode
|
on_testnet, // true if testnet mode
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
@ -514,7 +536,7 @@ async fn main() {
|
|||||||
));
|
));
|
||||||
#[cfg(feature = "simulation-mode")]
|
#[cfg(feature = "simulation-mode")]
|
||||||
tasks.spawn(net::mock_client(
|
tasks.spawn(net::mock_client(
|
||||||
network_router_port,
|
*ws_networking_port.unwrap_or(&9000),
|
||||||
our.name.clone(),
|
our.name.clone(),
|
||||||
kernel_message_sender.clone(),
|
kernel_message_sender.clone(),
|
||||||
net_message_receiver,
|
net_message_receiver,
|
||||||
|
@ -48,6 +48,8 @@ sol! {
|
|||||||
) public view virtual returns (bool authed);
|
) public view virtual returns (bool authed);
|
||||||
|
|
||||||
function nodes(bytes32) external view returns (address, uint96);
|
function nodes(bytes32) external view returns (address, uint96);
|
||||||
|
|
||||||
|
function ip(bytes32) external view returns (uint128, uint16, uint16, uint16, uint16);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _ip_to_number(ip: &str) -> Result<u32, &'static str> {
|
pub fn _ip_to_number(ip: &str) -> Result<u32, &'static str> {
|
||||||
@ -115,7 +117,8 @@ pub async fn register(
|
|||||||
tx: RegistrationSender,
|
tx: RegistrationSender,
|
||||||
kill_rx: oneshot::Receiver<bool>,
|
kill_rx: oneshot::Receiver<bool>,
|
||||||
ip: String,
|
ip: String,
|
||||||
port: u16,
|
ws_networking: (tokio::net::TcpListener, bool),
|
||||||
|
http_port: u16,
|
||||||
keyfile: Option<Vec<u8>>,
|
keyfile: Option<Vec<u8>>,
|
||||||
testnet: bool,
|
testnet: bool,
|
||||||
) {
|
) {
|
||||||
@ -124,14 +127,12 @@ pub async fn register(
|
|||||||
let net_keypair = Arc::new(serialized_networking_keypair.as_ref().to_vec());
|
let net_keypair = Arc::new(serialized_networking_keypair.as_ref().to_vec());
|
||||||
let tx = Arc::new(tx);
|
let tx = Arc::new(tx);
|
||||||
|
|
||||||
// TODO: if IP is localhost, don't allow registration as direct
|
let ws_port = ws_networking.0.local_addr().unwrap().port();
|
||||||
let ws_port = crate::http::utils::find_open_port(9000, 65535)
|
let ws_flag_used = ws_networking.1;
|
||||||
.await
|
|
||||||
.expect(
|
|
||||||
"Unable to find free port between 9000 and 65535 for a new websocket, are you kidding?",
|
|
||||||
);
|
|
||||||
|
|
||||||
// This is a temporary identity, passed to the UI. If it is confirmed through a /boot or /confirm-change-network-keys, then it will be used to replace the current identity
|
// This is a **temporary** identity, passed to the UI.
|
||||||
|
// If it is confirmed through a /boot or /confirm-change-network-keys,
|
||||||
|
// then it will be used to replace the current identity.
|
||||||
let our_temp_id = Arc::new(Identity {
|
let our_temp_id = Arc::new(Identity {
|
||||||
networking_key: format!("0x{}", public_key),
|
networking_key: format!("0x{}", public_key),
|
||||||
name: "".to_string(),
|
name: "".to_string(),
|
||||||
@ -167,6 +168,7 @@ pub async fn register(
|
|||||||
let net_keypair = warp::any().map(move || net_keypair.clone());
|
let net_keypair = warp::any().map(move || net_keypair.clone());
|
||||||
let tx = warp::any().map(move || tx.clone());
|
let tx = warp::any().map(move || tx.clone());
|
||||||
let ip = warp::any().map(move || ip.clone());
|
let ip = warp::any().map(move || ip.clone());
|
||||||
|
let ws_port = warp::any().map(move || if ws_flag_used { Some(ws_port) } else { None });
|
||||||
|
|
||||||
let static_files = warp::path("static").and(static_dir!("src/register-ui/build/static/"));
|
let static_files = warp::path("static").and(static_dir!("src/register-ui/build/static/"));
|
||||||
|
|
||||||
@ -197,7 +199,29 @@ pub async fn register(
|
|||||||
} else {
|
} else {
|
||||||
warp::reply::json(&"0xa")
|
warp::reply::json(&"0xa")
|
||||||
}
|
}
|
||||||
}));
|
}))
|
||||||
|
.or(warp::path("our").and(warp::get()).and(keyfile.clone()).map(
|
||||||
|
move |keyfile: Option<Vec<u8>>| {
|
||||||
|
if let Some(keyfile) = keyfile {
|
||||||
|
if let Ok((username, _, _, _, _, _)) = bincode::deserialize::<(
|
||||||
|
String,
|
||||||
|
Vec<String>,
|
||||||
|
Vec<u8>,
|
||||||
|
Vec<u8>,
|
||||||
|
Vec<u8>,
|
||||||
|
Vec<u8>,
|
||||||
|
)>(keyfile.as_ref())
|
||||||
|
{
|
||||||
|
return warp::reply::html(username);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
warp::reply::html(String::new())
|
||||||
|
},
|
||||||
|
));
|
||||||
|
|
||||||
|
let boot_provider = provider.clone();
|
||||||
|
let login_provider = provider.clone();
|
||||||
|
let import_provider = provider.clone();
|
||||||
|
|
||||||
let api = warp::path("info")
|
let api = warp::path("info")
|
||||||
.and(
|
.and(
|
||||||
@ -225,7 +249,7 @@ pub async fn register(
|
|||||||
.and(our_temp_id.clone())
|
.and(our_temp_id.clone())
|
||||||
.and(net_keypair.clone())
|
.and(net_keypair.clone())
|
||||||
.and_then(move |boot_info, tx, our_temp_id, net_keypair| {
|
.and_then(move |boot_info, tx, our_temp_id, net_keypair| {
|
||||||
let provider = provider.clone();
|
let boot_provider = boot_provider.clone();
|
||||||
handle_boot(
|
handle_boot(
|
||||||
boot_info,
|
boot_info,
|
||||||
tx,
|
tx,
|
||||||
@ -233,7 +257,7 @@ pub async fn register(
|
|||||||
net_keypair,
|
net_keypair,
|
||||||
testnet,
|
testnet,
|
||||||
kns_address,
|
kns_address,
|
||||||
provider,
|
boot_provider,
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
))
|
))
|
||||||
@ -242,17 +266,33 @@ pub async fn register(
|
|||||||
.and(warp::body::content_length_limit(1024 * 16))
|
.and(warp::body::content_length_limit(1024 * 16))
|
||||||
.and(warp::body::json())
|
.and(warp::body::json())
|
||||||
.and(ip.clone())
|
.and(ip.clone())
|
||||||
|
.and(ws_port.clone())
|
||||||
.and(tx.clone())
|
.and(tx.clone())
|
||||||
.and_then(handle_import_keyfile),
|
.and_then(move |boot_info, ip, ws_port, tx| {
|
||||||
|
let import_provider = import_provider.clone();
|
||||||
|
handle_import_keyfile(boot_info, ip, ws_port, tx, kns_address, import_provider)
|
||||||
|
}),
|
||||||
))
|
))
|
||||||
.or(warp::path("login").and(
|
.or(warp::path("login").and(
|
||||||
warp::post()
|
warp::post()
|
||||||
.and(warp::body::content_length_limit(1024 * 16))
|
.and(warp::body::content_length_limit(1024 * 16))
|
||||||
.and(warp::body::json())
|
.and(warp::body::json())
|
||||||
.and(ip)
|
.and(ip)
|
||||||
|
.and(ws_port.clone())
|
||||||
.and(tx.clone())
|
.and(tx.clone())
|
||||||
.and(keyfile.clone())
|
.and(keyfile.clone())
|
||||||
.and_then(handle_login),
|
.and_then(move |boot_info, ip, ws_port, tx, keyfile| {
|
||||||
|
let login_provider = login_provider.clone();
|
||||||
|
handle_login(
|
||||||
|
boot_info,
|
||||||
|
ip,
|
||||||
|
ws_port,
|
||||||
|
tx,
|
||||||
|
keyfile,
|
||||||
|
kns_address,
|
||||||
|
login_provider,
|
||||||
|
)
|
||||||
|
}),
|
||||||
))
|
))
|
||||||
.or(warp::path("confirm-change-network-keys").and(
|
.or(warp::path("confirm-change-network-keys").and(
|
||||||
warp::post()
|
warp::post()
|
||||||
@ -276,9 +316,9 @@ pub async fn register(
|
|||||||
.or(api)
|
.or(api)
|
||||||
.with(warp::reply::with::headers(headers));
|
.with(warp::reply::with::headers(headers));
|
||||||
|
|
||||||
let _ = open::that(format!("http://localhost:{}/", port));
|
let _ = open::that(format!("http://localhost:{}/", http_port));
|
||||||
warp::serve(routes)
|
warp::serve(routes)
|
||||||
.bind_with_graceful_shutdown(([0, 0, 0, 0], port), async {
|
.bind_with_graceful_shutdown(([0, 0, 0, 0], http_port), async {
|
||||||
kill_rx.await.ok();
|
kill_rx.await.ok();
|
||||||
})
|
})
|
||||||
.1
|
.1
|
||||||
@ -388,7 +428,25 @@ async fn handle_boot(
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let Ok(tld) = provider.call(tx, None).await else {
|
// this call can fail if the indexer has not caught up to the transaction
|
||||||
|
// that just got confirmed on our frontend. for this reason, we retry
|
||||||
|
// the call a few times before giving up.
|
||||||
|
|
||||||
|
let mut attempts = 0;
|
||||||
|
let mut tld_result = Err(());
|
||||||
|
while attempts < 5 {
|
||||||
|
match provider.call(tx.clone(), None).await {
|
||||||
|
Ok(tld) => {
|
||||||
|
tld_result = Ok(tld);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
attempts += 1;
|
||||||
|
tokio::time::sleep(tokio::time::Duration::from_secs(2)).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let Ok(tld) = tld_result else {
|
||||||
return Ok(warp::reply::with_status(
|
return Ok(warp::reply::with_status(
|
||||||
warp::reply::json(&"Failed to fetch TLD contract for username"),
|
warp::reply::json(&"Failed to fetch TLD contract for username"),
|
||||||
StatusCode::INTERNAL_SERVER_ERROR,
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
@ -419,13 +477,13 @@ async fn handle_boot(
|
|||||||
|
|
||||||
let Ok(authed) = provider.call(tx, None).await else {
|
let Ok(authed) = provider.call(tx, None).await else {
|
||||||
return Ok(warp::reply::with_status(
|
return Ok(warp::reply::with_status(
|
||||||
warp::reply::json(&"Failed to fetch TLD contract for username"),
|
warp::reply::json(&"Failed to fetch associated address for username"),
|
||||||
StatusCode::INTERNAL_SERVER_ERROR,
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
)
|
)
|
||||||
.into_response());
|
.into_response());
|
||||||
};
|
};
|
||||||
|
|
||||||
let is_ok = bool::abi_decode(&authed, false).map_err(|_| warp::reject())?;
|
let is_ok = bool::abi_decode(&authed, false).unwrap_or(false);
|
||||||
|
|
||||||
if !is_ok {
|
if !is_ok {
|
||||||
return Ok(warp::reply::with_status(
|
return Ok(warp::reply::with_status(
|
||||||
@ -482,7 +540,10 @@ async fn handle_boot(
|
|||||||
async fn handle_import_keyfile(
|
async fn handle_import_keyfile(
|
||||||
info: ImportKeyfileInfo,
|
info: ImportKeyfileInfo,
|
||||||
ip: String,
|
ip: String,
|
||||||
|
ws_networking_port: Option<u16>,
|
||||||
sender: Arc<RegistrationSender>,
|
sender: Arc<RegistrationSender>,
|
||||||
|
kns_address: EthAddress,
|
||||||
|
provider: Arc<Provider<PubSubFrontend>>,
|
||||||
) -> Result<impl Reply, Rejection> {
|
) -> Result<impl Reply, Rejection> {
|
||||||
// if keyfile was not present in node and is present from user upload
|
// if keyfile was not present in node and is present from user upload
|
||||||
let encoded_keyfile = match base64::decode(info.keyfile.clone()) {
|
let encoded_keyfile = match base64::decode(info.keyfile.clone()) {
|
||||||
@ -496,58 +557,52 @@ async fn handle_import_keyfile(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some(ws_port) = crate::http::utils::find_open_port(9000, 9999).await else {
|
let (decoded_keyfile, mut our) =
|
||||||
|
match keygen::decode_keyfile(&encoded_keyfile, &info.password_hash) {
|
||||||
|
Ok(k) => {
|
||||||
|
let our = Identity {
|
||||||
|
name: k.username.clone(),
|
||||||
|
networking_key: format!(
|
||||||
|
"0x{}",
|
||||||
|
hex::encode(k.networking_keypair.public_key().as_ref())
|
||||||
|
),
|
||||||
|
ws_routing: if k.routers.is_empty() {
|
||||||
|
Some((ip, 9000))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
allowed_routers: k.routers.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
|
(k, our)
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
return Ok(warp::reply::with_status(
|
||||||
|
warp::reply::json(&"Incorrect password_hash".to_string()),
|
||||||
|
StatusCode::UNAUTHORIZED,
|
||||||
|
)
|
||||||
|
.into_response())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Err(e) = assign_ws_routing(&mut our, kns_address, provider, ws_networking_port).await {
|
||||||
return Ok(warp::reply::with_status(
|
return Ok(warp::reply::with_status(
|
||||||
warp::reply::json(&"Unable to find free port"),
|
warp::reply::json(&e.to_string()),
|
||||||
StatusCode::INTERNAL_SERVER_ERROR,
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
)
|
)
|
||||||
.into_response());
|
.into_response());
|
||||||
};
|
}
|
||||||
|
|
||||||
let (decoded_keyfile, our) = match keygen::decode_keyfile(&encoded_keyfile, &info.password_hash)
|
|
||||||
{
|
|
||||||
Ok(k) => {
|
|
||||||
let our = Identity {
|
|
||||||
name: k.username.clone(),
|
|
||||||
networking_key: format!(
|
|
||||||
"0x{}",
|
|
||||||
hex::encode(k.networking_keypair.public_key().as_ref())
|
|
||||||
),
|
|
||||||
ws_routing: if k.routers.is_empty() {
|
|
||||||
Some((ip, ws_port))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
},
|
|
||||||
allowed_routers: k.routers.clone(),
|
|
||||||
};
|
|
||||||
|
|
||||||
(k, our)
|
|
||||||
}
|
|
||||||
Err(_) => {
|
|
||||||
return Ok(warp::reply::with_status(
|
|
||||||
warp::reply::json(&"Incorrect password_hash".to_string()),
|
|
||||||
StatusCode::UNAUTHORIZED,
|
|
||||||
)
|
|
||||||
.into_response())
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// if !networking_info_valid(rpc_url, ip, ws_port, &our).await {
|
|
||||||
// return Ok(warp::reply::with_status(
|
|
||||||
// warp::reply::json(&"Networking info invalid".to_string()),
|
|
||||||
// StatusCode::UNAUTHORIZED,
|
|
||||||
// )
|
|
||||||
// .into_response());
|
|
||||||
// }
|
|
||||||
|
|
||||||
success_response(sender, our, decoded_keyfile, encoded_keyfile).await
|
success_response(sender, our, decoded_keyfile, encoded_keyfile).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_login(
|
async fn handle_login(
|
||||||
info: LoginInfo,
|
info: LoginInfo,
|
||||||
ip: String,
|
ip: String,
|
||||||
|
ws_networking_port: Option<u16>,
|
||||||
sender: Arc<RegistrationSender>,
|
sender: Arc<RegistrationSender>,
|
||||||
encoded_keyfile: Option<Vec<u8>>,
|
encoded_keyfile: Option<Vec<u8>>,
|
||||||
|
kns_address: EthAddress,
|
||||||
|
provider: Arc<Provider<PubSubFrontend>>,
|
||||||
) -> Result<impl Reply, Rejection> {
|
) -> Result<impl Reply, Rejection> {
|
||||||
if encoded_keyfile.is_none() {
|
if encoded_keyfile.is_none() {
|
||||||
return Ok(warp::reply::with_status(
|
return Ok(warp::reply::with_status(
|
||||||
@ -558,42 +613,41 @@ async fn handle_login(
|
|||||||
}
|
}
|
||||||
let encoded_keyfile = encoded_keyfile.unwrap();
|
let encoded_keyfile = encoded_keyfile.unwrap();
|
||||||
|
|
||||||
let Some(ws_port) = crate::http::utils::find_open_port(9000, 65535).await else {
|
let (decoded_keyfile, mut our) =
|
||||||
|
match keygen::decode_keyfile(&encoded_keyfile, &info.password_hash) {
|
||||||
|
Ok(k) => {
|
||||||
|
let our = Identity {
|
||||||
|
name: k.username.clone(),
|
||||||
|
networking_key: format!(
|
||||||
|
"0x{}",
|
||||||
|
hex::encode(k.networking_keypair.public_key().as_ref())
|
||||||
|
),
|
||||||
|
ws_routing: if k.routers.is_empty() {
|
||||||
|
Some((ip, 9000))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
allowed_routers: k.routers.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
|
(k, our)
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
return Ok(warp::reply::with_status(
|
||||||
|
warp::reply::json(&"Incorrect password_hash"),
|
||||||
|
StatusCode::UNAUTHORIZED,
|
||||||
|
)
|
||||||
|
.into_response())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Err(e) = assign_ws_routing(&mut our, kns_address, provider, ws_networking_port).await {
|
||||||
return Ok(warp::reply::with_status(
|
return Ok(warp::reply::with_status(
|
||||||
warp::reply::json(&"Unable to find free port"),
|
warp::reply::json(&e.to_string()),
|
||||||
StatusCode::INTERNAL_SERVER_ERROR,
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
)
|
)
|
||||||
.into_response());
|
.into_response());
|
||||||
};
|
}
|
||||||
|
|
||||||
let (decoded_keyfile, our) = match keygen::decode_keyfile(&encoded_keyfile, &info.password_hash)
|
|
||||||
{
|
|
||||||
Ok(k) => {
|
|
||||||
let our = Identity {
|
|
||||||
name: k.username.clone(),
|
|
||||||
networking_key: format!(
|
|
||||||
"0x{}",
|
|
||||||
hex::encode(k.networking_keypair.public_key().as_ref())
|
|
||||||
),
|
|
||||||
ws_routing: if k.routers.is_empty() {
|
|
||||||
Some((ip, ws_port))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
},
|
|
||||||
allowed_routers: k.routers.clone(),
|
|
||||||
};
|
|
||||||
|
|
||||||
(k, our)
|
|
||||||
}
|
|
||||||
Err(_) => {
|
|
||||||
return Ok(warp::reply::with_status(
|
|
||||||
warp::reply::json(&"Incorrect password_hash"),
|
|
||||||
StatusCode::UNAUTHORIZED,
|
|
||||||
)
|
|
||||||
.into_response())
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
success_response(sender, our, decoded_keyfile, encoded_keyfile).await
|
success_response(sender, our, decoded_keyfile, encoded_keyfile).await
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -657,6 +711,54 @@ async fn confirm_change_network_keys(
|
|||||||
success_response(sender, our.clone(), decoded_keyfile, encoded_keyfile).await
|
success_response(sender, our.clone(), decoded_keyfile, encoded_keyfile).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn assign_ws_routing(
|
||||||
|
our: &mut Identity,
|
||||||
|
kns_address: EthAddress,
|
||||||
|
provider: Arc<Provider<PubSubFrontend>>,
|
||||||
|
ws_networking_port: Option<u16>,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let namehash = FixedBytes::<32>::from_slice(&keygen::namehash(&our.name));
|
||||||
|
let ip_call = ipCall { _0: namehash }.abi_encode();
|
||||||
|
let tx_input = TransactionInput::new(Bytes::from(ip_call));
|
||||||
|
let tx = TransactionRequest {
|
||||||
|
to: Some(kns_address),
|
||||||
|
input: tx_input,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let Ok(ip_data) = provider.call(tx, None).await else {
|
||||||
|
return Err(anyhow::anyhow!("Failed to fetch node IP data from PKI"));
|
||||||
|
};
|
||||||
|
|
||||||
|
let Ok((ip, ws, _wt, _tcp, _udp)) = <(u128, u16, u16, u16, u16)>::abi_decode(&ip_data, false)
|
||||||
|
else {
|
||||||
|
return Err(anyhow::anyhow!("Failed to decode node IP data from PKI"));
|
||||||
|
};
|
||||||
|
|
||||||
|
let node_ip = format!(
|
||||||
|
"{}.{}.{}.{}",
|
||||||
|
(ip >> 24) & 0xFF,
|
||||||
|
(ip >> 16) & 0xFF,
|
||||||
|
(ip >> 8) & 0xFF,
|
||||||
|
ip & 0xFF
|
||||||
|
);
|
||||||
|
|
||||||
|
if node_ip != *"0.0.0.0" || ws != 0 {
|
||||||
|
// direct node
|
||||||
|
if let Some(chosen_port) = ws_networking_port {
|
||||||
|
if chosen_port != ws {
|
||||||
|
return Err(anyhow::anyhow!(
|
||||||
|
"Binary used --ws-port flag to set port to {}, but node is using port {} onchain.",
|
||||||
|
chosen_port,
|
||||||
|
ws
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
our.ws_routing = Some((node_ip, ws));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
async fn success_response(
|
async fn success_response(
|
||||||
sender: Arc<RegistrationSender>,
|
sender: Arc<RegistrationSender>,
|
||||||
our: Identity,
|
our: Identity,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "lib"
|
name = "lib"
|
||||||
authors = ["KinodeDAO"]
|
authors = ["KinodeDAO"]
|
||||||
version = "0.6.1"
|
version = "0.6.2"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "A general-purpose sovereign cloud computing platform"
|
description = "A general-purpose sovereign cloud computing platform"
|
||||||
homepage = "https://kinode.org"
|
homepage = "https://kinode.org"
|
||||||
|
Loading…
Reference in New Issue
Block a user