fixed network ync startup process

This commit is contained in:
viraladmin 2026-06-13 19:36:03 -06:00
parent b8c8e47b69
commit 0e852e0e69
11 changed files with 215 additions and 97 deletions

View File

@ -1,7 +1,7 @@
use super::*; use super::*;
pub async fn signature_exists(signature: &str, hash: &str) -> Result<bool> { pub async fn signature_exists(signature: &str, hash: &str) -> Result<bool> {
let client_handle = db_client().await?; let client_handle = db_client().await?;
let client = client_handle.as_ref(); let client = client_handle.as_ref();
// Check every mempool table because the signature column names differ by // Check every mempool table because the signature column names differ by
@ -148,6 +148,124 @@ pub async fn transactions_by_address(db: &Db, address: &str) -> RpcResponse {
RpcResponse::Binary(bytes) RpcResponse::Binary(bytes)
} }
pub async fn latest_pending_txids_by_address(db: &Db, address: &str, limit: usize) -> Vec<Vec<u8>> {
if limit == 0 {
return Vec::new();
}
let client_handle = match db_client().await {
Ok(client) => client,
Err(_) => return Vec::new(),
};
let client = client_handle.as_ref();
let addresses = canonical_mempool_addresses(db, address);
let limit = i64::try_from(limit).unwrap_or(i64::MAX);
let rows = match client
.query(
r#"
SELECT hash FROM (
SELECT DISTINCT ON (hash) hash, time, source_id FROM (
SELECT hash, time, id AS source_id FROM transfer
WHERE (sender = ANY($1) OR receiver = ANY($1)) AND processed = false
UNION ALL
SELECT hash, time, id AS source_id FROM token
WHERE creator = ANY($1) AND processed = false
UNION ALL
SELECT hash, time, id AS source_id FROM issue_token
WHERE creator = ANY($1) AND processed = false
UNION ALL
SELECT hash, time, id AS source_id FROM burn
WHERE address = ANY($1) AND processed = false
UNION ALL
SELECT hash, time, id AS source_id FROM nft
WHERE creator = ANY($1) AND processed = false
UNION ALL
SELECT hash, time, id AS source_id FROM marketing
WHERE advertiser = ANY($1) AND processed = false
UNION ALL
SELECT hash, time, id AS source_id FROM vanity_address
WHERE address = ANY($1) AND processed = false
UNION ALL
SELECT hash, time, id AS source_id FROM swap
WHERE (sender1 = ANY($1) OR sender2 = ANY($1)) AND processed = false
UNION ALL
SELECT hash, time, id AS source_id FROM loan_contract
WHERE (lender = ANY($1) OR borrower = ANY($1)) AND processed = false
UNION ALL
SELECT hash, time, id AS source_id FROM loan_payment
WHERE address = ANY($1) AND processed = false
UNION ALL
SELECT hash, time, id AS source_id FROM collateral_claim
WHERE address = ANY($1) AND processed = false
) AS pending
ORDER BY hash, time DESC, source_id DESC
) AS deduped
ORDER BY time DESC, source_id DESC
LIMIT $2
"#,
&[&addresses, &limit],
)
.await
{
Ok(rows) => rows,
Err(_) => return Vec::new(),
};
let mut txids = rows
.into_iter()
.filter_map(|row| {
let hash: String = row.get("hash");
decode(&hash).ok().filter(|bytes| bytes.len() == 32)
})
.collect::<Vec<_>>();
txids.truncate(limit as usize);
txids
}
pub async fn pending_transaction_by_txid(txid: &[u8]) -> Option<Vec<u8>> {
if txid.len() != 32 {
return None;
}
let client_handle = db_client().await.ok()?;
let client = client_handle.as_ref();
let hash = crate::encode(txid);
let row = client
.query_opt(
r#"
SELECT original FROM (
SELECT original FROM transfer WHERE hash = $1 AND processed = false
UNION ALL
SELECT original FROM token WHERE hash = $1 AND processed = false
UNION ALL
SELECT original FROM issue_token WHERE hash = $1 AND processed = false
UNION ALL
SELECT original FROM burn WHERE hash = $1 AND processed = false
UNION ALL
SELECT original FROM nft WHERE hash = $1 AND processed = false
UNION ALL
SELECT original FROM marketing WHERE hash = $1 AND processed = false
UNION ALL
SELECT original FROM vanity_address WHERE hash = $1 AND processed = false
UNION ALL
SELECT original FROM swap WHERE hash = $1 AND processed = false
UNION ALL
SELECT original FROM loan_contract WHERE hash = $1 AND processed = false
UNION ALL
SELECT original FROM loan_payment WHERE hash = $1 AND processed = false
UNION ALL
SELECT original FROM collateral_claim WHERE hash = $1 AND processed = false
) AS subquery LIMIT 1
"#,
&[&hash],
)
.await
.ok()?;
row.map(|row| row.get("original"))
}
pub async fn largest_fee() -> RpcResponse { pub async fn largest_fee() -> RpcResponse {
let client_handle = match db_client().await { let client_handle = match db_client().await {
Ok(client) => client, Ok(client) => client,
@ -204,7 +322,7 @@ async fn pending_saved_loan_payment_balance(
addresses: &[String], addresses: &[String],
coin: &str, coin: &str,
) -> Result<u64, Box<dyn std::error::Error + Send + Sync>> { ) -> Result<u64, Box<dyn std::error::Error + Send + Sync>> {
let client_handle = db_client().await?; let client_handle = db_client().await?;
let client = client_handle.as_ref(); let client = client_handle.as_ref();
let rows = client let rows = client
.query( .query(
@ -258,7 +376,7 @@ pub async fn get_coin_balance(
address: &str, address: &str,
coin: &str, coin: &str,
) -> Result<u64, Box<dyn std::error::Error + Send + Sync>> { ) -> Result<u64, Box<dyn std::error::Error + Send + Sync>> {
let client_handle = db_client().await?; let client_handle = db_client().await?;
let client = client_handle.as_ref(); let client = client_handle.as_ref();
// Pending-balance checks use canonical addresses so vanity and short // Pending-balance checks use canonical addresses so vanity and short
// address inputs see the same outgoing obligations. // address inputs see the same outgoing obligations.
@ -339,7 +457,7 @@ pub async fn get_basecoin_balance(
db: &Db, db: &Db,
address: &str, address: &str,
) -> Result<u64, Box<dyn std::error::Error + Send + Sync>> { ) -> Result<u64, Box<dyn std::error::Error + Send + Sync>> {
let client_handle = db_client().await?; let client_handle = db_client().await?;
let client = client_handle.as_ref(); let client = client_handle.as_ref();
let addresses = canonical_mempool_addresses(db, address); let addresses = canonical_mempool_addresses(db, address);
@ -403,7 +521,7 @@ pub async fn get_basecoin_balance(
pub async fn get_pending_payments_for_contract( pub async fn get_pending_payments_for_contract(
contract_hash: &str, contract_hash: &str,
) -> Result<u64, Box<dyn std::error::Error + Send + Sync>> { ) -> Result<u64, Box<dyn std::error::Error + Send + Sync>> {
let client_handle = db_client().await?; let client_handle = db_client().await?;
let client = client_handle.as_ref(); let client = client_handle.as_ref();
// Mempool/UI callers can use this for unconfirmed payment visibility. // Mempool/UI callers can use this for unconfirmed payment visibility.

View File

@ -207,7 +207,8 @@ mod selection;
pub use lookups::{ pub use lookups::{
get_basecoin_balance, get_coin_balance, get_pending_payments_for_contract, largest_fee, get_basecoin_balance, get_coin_balance, get_pending_payments_for_contract, largest_fee,
signature_exists, total_transactions, transaction_by_signature, transactions_by_address, latest_pending_txids_by_address, pending_transaction_by_txid, signature_exists,
total_transactions, transaction_by_signature, transactions_by_address,
}; };
pub use processing::{ pub use processing::{
delete_by_signatures, mark_processed_by_signatures, mark_selected_transactions_processed, delete_by_signatures, mark_processed_by_signatures, mark_selected_transactions_processed,

View File

@ -12,7 +12,7 @@ impl NodeInfo {
db: &Db, db: &Db,
edit: SignedNodeEdit, edit: SignedNodeEdit,
monitors: Vec<String>, monitors: Vec<String>,
blocks_mined: u8, _blocks_mined: u8,
) -> Result<(), String> { ) -> Result<(), String> {
if !is_public_network_address(&edit.ip) { if !is_public_network_address(&edit.ip) {
return Err("invalid network address".to_string()); return Err("invalid network address".to_string());
@ -43,29 +43,24 @@ impl NodeInfo {
let mut address_map = ADDRESS_MAP.lock().await; let mut address_map = ADDRESS_MAP.lock().await;
if let Some(existing_node) = address_map.get_mut(&edit.address) { if let Some(existing_node) = address_map.get_mut(&edit.address) {
existing_node.monitoring = monitors.clone(); existing_node.monitoring = monitors.clone();
existing_node.blocks_mined = blocks_mined;
if existing_node.deleted_timestamp > 0 { if existing_node.deleted_timestamp > 0 {
if existing_node.ip == edit.ip { existing_node.ip = edit.ip;
existing_node.added_by = edit.modified_by;
existing_node.added_timestamp = edit.modified_timestamp;
existing_node.added_signature = edit.modified_signature;
existing_node.deleted_timestamp = 0_u64;
existing_node.deleted_block = 0_u32;
drop(address_map);
Self::persist_recovery_snapshot("import revive").await;
return Ok(());
} else {
if existing_node.ip != edit.ip {
return Err("active node must be deleted before changing IP".to_string());
}
if edit.modified_timestamp > existing_node.added_timestamp {
existing_node.added_by = edit.modified_by; existing_node.added_by = edit.modified_by;
existing_node.added_timestamp = edit.modified_timestamp; existing_node.added_timestamp = edit.modified_timestamp;
existing_node.added_signature = edit.modified_signature; existing_node.added_signature = edit.modified_signature;
existing_node.deleted_timestamp = 0_u64;
existing_node.deleted_block = 0_u32;
drop(address_map);
Self::persist_recovery_snapshot("import revive").await;
return Ok(());
}
address_map.remove(&edit.address);
} else {
if edit.modified_timestamp > existing_node.added_timestamp {
*existing_node = NodeInfo::new(
edit.ip,
blocks_mined,
edit.modified_by,
edit.modified_timestamp,
edit.modified_signature,
);
existing_node.monitoring = monitors; existing_node.monitoring = monitors;
} }
drop(address_map); drop(address_map);
@ -74,17 +69,18 @@ impl NodeInfo {
} }
} }
if address_map let inherited_blocks_mined = match address_map.values().find(|node| node.ip == edit.ip) {
.values() Some(node) if node.deleted_timestamp == 0 && edit.ip != GENESIS_IP => {
.any(|node| node.ip == edit.ip && node.deleted_timestamp == 0 && edit.ip != GENESIS_IP) return Err("ip already exists".to_string());
{ }
return Err("ip already exists".to_string()); Some(node) => node.blocks_mined,
} None => 0,
};
address_map.insert(edit.address, { address_map.insert(edit.address, {
let mut node = NodeInfo::new( let mut node = NodeInfo::new(
edit.ip, edit.ip,
blocks_mined, inherited_blocks_mined,
edit.modified_by, edit.modified_by,
edit.modified_timestamp, edit.modified_timestamp,
edit.modified_signature, edit.modified_signature,
@ -209,7 +205,7 @@ impl NodeInfo {
map, map,
mut edit, mut edit,
monitors, monitors,
mut blocks_mined, blocks_mined: _blocks_mined,
remote_ip, remote_ip,
db, db,
wallet, wallet,
@ -235,10 +231,6 @@ impl NodeInfo {
Self::added_signature(&edit.address, &edit.ip, current_timestamp, &wallet).await; Self::added_signature(&edit.address, &edit.ip, current_timestamp, &wallet).await;
} }
if !remote_ip.is_empty() {
blocks_mined = 0;
}
let data = format!( let data = format!(
"{}{}{}{}", "{}{}{}{}",
edit.address, edit.ip, edit.modified_by, edit.modified_timestamp edit.address, edit.ip, edit.modified_by, edit.modified_timestamp
@ -318,26 +310,23 @@ impl NodeInfo {
if let Some(existing_node) = address_map.get_mut(&edit.address) { if let Some(existing_node) = address_map.get_mut(&edit.address) {
existing_node.monitoring = monitors.clone(); existing_node.monitoring = monitors.clone();
if existing_node.deleted_timestamp > 0 { if existing_node.deleted_timestamp > 0 {
if existing_node.ip == edit.ip { existing_node.ip = edit.ip.clone();
existing_node.added_by = edit.modified_by.clone();
existing_node.added_timestamp = edit.modified_timestamp;
existing_node.added_signature = edit.modified_signature.clone();
existing_node.deleted_timestamp = 0_u64;
existing_node.deleted_block = 0_u32;
state_changed = true;
} else {
if existing_node.ip != edit.ip {
return RpcResponse::Binary(
b"Error: Active node must be deleted before changing IP".to_vec(),
);
}
if edit.modified_timestamp > existing_node.added_timestamp {
existing_node.added_by = edit.modified_by.clone(); existing_node.added_by = edit.modified_by.clone();
existing_node.added_timestamp = edit.modified_timestamp; existing_node.added_timestamp = edit.modified_timestamp;
existing_node.added_signature = edit.modified_signature.clone(); existing_node.added_signature = edit.modified_signature.clone();
existing_node.blocks_mined = blocks_mined;
existing_node.deleted_timestamp = 0_u64;
existing_node.deleted_block = 0_u32;
state_changed = true;
} else {
address_map.remove(&edit.address);
}
} else {
if edit.modified_timestamp > existing_node.added_timestamp {
*existing_node = NodeInfo::new(
edit.ip.clone(),
blocks_mined,
edit.modified_by.clone(),
edit.modified_timestamp,
edit.modified_signature.clone(),
);
existing_node.monitoring = monitors.clone(); existing_node.monitoring = monitors.clone();
state_changed = true; state_changed = true;
} }
@ -345,11 +334,14 @@ impl NodeInfo {
} }
if !address_map.contains_key(&edit.address) { if !address_map.contains_key(&edit.address) {
let mut inherited_blocks_mined = 0;
if let Some(existing_node) = if let Some(existing_node) =
address_map.values_mut().find(|node| node.ip == edit.ip) address_map.values_mut().find(|node| node.ip == edit.ip)
{ {
if existing_node.deleted_timestamp == 0 && edit.ip != GENESIS_IP { if existing_node.deleted_timestamp == 0 && edit.ip != GENESIS_IP {
penalize_duplicate_ip = true; penalize_duplicate_ip = true;
} else {
inherited_blocks_mined = existing_node.blocks_mined;
} }
} }
@ -359,7 +351,7 @@ impl NodeInfo {
address_map.insert(edit.address.clone(), { address_map.insert(edit.address.clone(), {
let mut node = NodeInfo::new( let mut node = NodeInfo::new(
edit.ip.clone(), edit.ip.clone(),
blocks_mined, inherited_blocks_mined,
edit.modified_by.clone(), edit.modified_by.clone(),
edit.modified_timestamp, edit.modified_timestamp,
edit.modified_signature.clone(), edit.modified_signature.clone(),

View File

@ -2,6 +2,13 @@ use super::*;
use crate::common::check_genesis::genesis_checkup; use crate::common::check_genesis::genesis_checkup;
use crate::records::unpack_block::unpack_header::load_block_header; use crate::records::unpack_block::unpack_header::load_block_header;
fn increment_count(counts: &mut HashMap<String, u8>, address: &str) {
let entry = counts.entry(address.to_string()).or_insert(0);
if *entry < 250 {
*entry += 1;
}
}
impl NodeInfo { impl NodeInfo {
pub async fn increment_mined(address: &str) { pub async fn increment_mined(address: &str) {
{ {
@ -48,8 +55,7 @@ impl NodeInfo {
} }
let mut mined_count = 0_u8; let mut mined_count = 0_u8;
let start_height = if through_height > 0 { 1 } else { 0 }; for block_number in 1..=through_height {
for block_number in start_height..=through_height {
let header = load_block_header(block_number).await?; let header = load_block_header(block_number).await?;
if header.unmined_block.miner == address { if header.unmined_block.miner == address {
mined_count = mined_count.saturating_add(1); mined_count = mined_count.saturating_add(1);
@ -102,15 +108,10 @@ impl NodeInfo {
return Ok(()); return Ok(());
} }
let start_height = if current_height > 0 { 1 } else { 0 }; for block_number in 1..=current_height {
for block_number in start_height..=current_height {
let header = load_block_header(block_number).await?; let header = load_block_header(block_number).await?;
let miner = header.unmined_block.miner; let miner = header.unmined_block.miner;
let entry = mined_counts.entry(miner).or_insert(0); increment_count(&mut mined_counts, &miner);
// Keep the rebuilt value under the same cap as live increments.
if *entry < 250 {
*entry += 1;
}
} }
{ {

View File

@ -11,7 +11,7 @@ use crate::records::ip_score::score::update_ip_score;
use crate::records::memory::connections::CONNECTIONS; use crate::records::memory::connections::CONNECTIONS;
use crate::records::memory::network_mapping::enums::NodeEditType; use crate::records::memory::network_mapping::enums::NodeEditType;
use crate::records::memory::network_mapping::structs::{ use crate::records::memory::network_mapping::structs::{
AddAddressParams, DeleteAddressParams, MonitorAddressParams, SignedMonitorEdit, SignedNodeEdit, AddAddressParams, MonitorAddressParams, SignedMonitorEdit, SignedNodeEdit,
NODE_RECORD_FIXED_BYTES, NODE_RECORD_FIXED_BYTES,
}; };
use crate::records::memory::response_channels::Command; use crate::records::memory::response_channels::Command;
@ -61,7 +61,6 @@ impl NodeInfo {
} }
mod add; mod add;
mod delete;
pub mod enums; pub mod enums;
mod mined_counts; mod mined_counts;
pub(crate) mod monitor; pub(crate) mod monitor;

View File

@ -56,17 +56,6 @@ pub struct AddAddressParams {
pub connections_key: String, pub connections_key: String,
} }
// DeleteAddressParams groups the shared context needed to remove a node from the network map.
#[derive(Clone)]
pub struct DeleteAddressParams {
pub map: Arc<Mutex<Command>>,
pub edit: SignedNodeEdit,
pub remote_ip: String,
pub db: Db,
pub wallet: Arc<Wallet>,
pub connections_key: String,
}
#[derive(Clone)] #[derive(Clone)]
pub struct MonitorAddressParams { pub struct MonitorAddressParams {
pub map: Arc<Mutex<Command>>, pub map: Arc<Mutex<Command>>,

View File

@ -40,7 +40,6 @@ pub const RPC_VALIDATE_MESSAGE: u8 = 25;
pub const RPC_BLOCK_IP: u8 = 26; pub const RPC_BLOCK_IP: u8 = 26;
pub const RPC_UNBLOCK_IP: u8 = 27; pub const RPC_UNBLOCK_IP: u8 = 27;
pub const RPC_ADD_NETWORK_NODE: u8 = 28; pub const RPC_ADD_NETWORK_NODE: u8 = 28;
pub const RPC_DELETE_NETWORK_NODE: u8 = 29;
pub const RPC_REQUEST_NODE_LIST: u8 = 30; pub const RPC_REQUEST_NODE_LIST: u8 = 30;
pub const RPC_TOKEN_LIST: u8 = 31; pub const RPC_TOKEN_LIST: u8 = 31;
pub const RPC_NFT_LIST: u8 = 32; pub const RPC_NFT_LIST: u8 = 32;

View File

@ -1,7 +1,9 @@
use crate::records::memory::mempool::latest_pending_txids_by_address;
use crate::records::record_chain::wallet_tx_index::WALLET_TX_INDEX_TREE; use crate::records::record_chain::wallet_tx_index::WALLET_TX_INDEX_TREE;
use crate::rpc::responses::RpcResponse; use crate::rpc::responses::RpcResponse;
use crate::sled::Db; use crate::sled::Db;
use crate::wallets::structures::Wallet; use crate::wallets::structures::Wallet;
use std::collections::HashSet;
use std::ops::Bound; use std::ops::Bound;
const TXID_LENGTH: usize = 32; const TXID_LENGTH: usize = 32;
@ -91,6 +93,10 @@ pub async fn latest(address_bytes: Vec<u8>, limit: u32, db: &Db) -> RpcResponse
return RpcResponse::Binary(Vec::new()); return RpcResponse::Binary(Vec::new());
} }
let Some(address) = Wallet::bytes_to_short_address(&address_bytes) else {
return RpcResponse::Binary(b"error: Invalid wallet address bytes".to_vec());
};
let tree = match db.open_tree(WALLET_TX_INDEX_TREE) { let tree = match db.open_tree(WALLET_TX_INDEX_TREE) {
Ok(tree) => tree, Ok(tree) => tree,
Err(err) => { Err(err) => {
@ -103,6 +109,19 @@ pub async fn latest(address_bytes: Vec<u8>, limit: u32, db: &Db) -> RpcResponse
let (start, end) = history_bounds(&address_bytes); let (start, end) = history_bounds(&address_bytes);
let mut found = 0usize; let mut found = 0usize;
let mut txids = Vec::with_capacity(limit * TXID_LENGTH); let mut txids = Vec::with_capacity(limit * TXID_LENGTH);
let mut seen = HashSet::new();
for txid in latest_pending_txids_by_address(db, &address, limit).await {
if txid.len() != TXID_LENGTH || !seen.insert(txid.clone()) {
continue;
}
txids.extend_from_slice(&txid);
found += 1;
if found >= limit {
return RpcResponse::Binary(txids);
}
}
for entry in tree.range((start, end)).rev() { for entry in tree.range((start, end)).rev() {
let (_key, value) = match entry { let (_key, value) = match entry {
@ -118,7 +137,12 @@ pub async fn latest(address_bytes: Vec<u8>, limit: u32, db: &Db) -> RpcResponse
continue; continue;
} }
txids.extend_from_slice(&value); let txid = value.to_vec();
if !seen.insert(txid.clone()) {
continue;
}
txids.extend_from_slice(&txid);
found += 1; found += 1;
if found >= limit { if found >= limit {
break; break;

View File

@ -13,7 +13,6 @@ pub mod block_headers;
pub mod block_height; pub mod block_height;
pub mod block_peer_ip; pub mod block_peer_ip;
pub mod contract; pub mod contract;
pub mod delete_network_node;
pub mod difficulty; pub mod difficulty;
pub mod largest_tx_fee; pub mod largest_tx_fee;
pub mod latest_block; pub mod latest_block;

View File

@ -2,6 +2,7 @@ use crate::blocks::block::VRF_BLOCK_BYTES;
use crate::common::binary_conversions::binary_to_string; use crate::common::binary_conversions::binary_to_string;
use crate::common::network_paths_and_settings::block_extension_and_paths; use crate::common::network_paths_and_settings::block_extension_and_paths;
use crate::io; use crate::io;
use crate::records::memory::mempool::pending_transaction_by_txid;
use crate::rpc::command_maps; use crate::rpc::command_maps;
use crate::rpc::responses::RpcResponse; use crate::rpc::responses::RpcResponse;
use crate::sled::Db; use crate::sled::Db;
@ -32,7 +33,7 @@ pub async fn request_transaction_by_txid(db: &Db, txid: Vec<u8>) -> RpcResponse
pub async fn request_transaction_by_txid_with_block(db: &Db, txid: Vec<u8>) -> RpcResponse { pub async fn request_transaction_by_txid_with_block(db: &Db, txid: Vec<u8>) -> RpcResponse {
// Some callers need the block number alongside the raw transaction // Some callers need the block number alongside the raw transaction
// bytes, so this variant prefixes the payload with the block height. // bytes, so this variant prefixes the payload with the block height.
match lookup_transaction_location(db, txid).await { match lookup_transaction_location(db, txid.clone()).await {
Ok((block, position, block_filename)) => { Ok((block, position, block_filename)) => {
let bytes = calculate_offset(&block_filename, position).await; let bytes = calculate_offset(&block_filename, position).await;
match bytes { match bytes {
@ -48,7 +49,16 @@ pub async fn request_transaction_by_txid_with_block(db: &Db, txid: Vec<u8>) -> R
} }
} }
} }
Err(msg) => RpcResponse::Binary(msg.into_bytes()), Err(msg) => {
if let Some(bytes) = pending_transaction_by_txid(&txid).await {
let mut response = Vec::with_capacity(4 + bytes.len());
response.extend_from_slice(&0u32.to_le_bytes());
response.extend_from_slice(&bytes);
RpcResponse::Binary(response)
} else {
RpcResponse::Binary(msg.into_bytes())
}
}
} }
} }

View File

@ -567,20 +567,6 @@ pub async fn start_loop(
.send(&stream_locked, Some(&connections_key), uid) .send(&stream_locked, Some(&connections_key), uid)
.await; .await;
} }
29 => {
// delete a new network node
let (uid, result) = commands::delete_network_node::delete_network_node(
&connections_key,
stream_locked.clone(),
&db,
wallet.clone(),
map.clone(),
)
.await?;
result
.send(&stream_locked, Some(&connections_key), uid)
.await;
}
30 => { 30 => {
// request node list // request node list
let (uid, _) = read_bytes_from_stream::read_uid_from_stream( let (uid, _) = read_bytes_from_stream::read_uid_from_stream(