diff --git a/src/records/memory/connections.rs b/src/records/memory/connections.rs index a76dc65..2c10001 100644 --- a/src/records/memory/connections.rs +++ b/src/records/memory/connections.rs @@ -122,6 +122,7 @@ async fn reconnect_replacement_inner(excluded_ip: &str) { db: context.db, map: context.map, first: false, + run_startup_sync: false, }; if let Err(err) = bootstrap_peer_discovery(bootstrap_params).await { diff --git a/src/rpc/client/handshake_processing.rs b/src/rpc/client/handshake_processing.rs index c5a6892..06180b8 100644 --- a/src/rpc/client/handshake_processing.rs +++ b/src/rpc/client/handshake_processing.rs @@ -55,6 +55,7 @@ pub struct BootstrapParams { pub db: Db, pub map: Arc>, pub first: bool, + pub run_startup_sync: bool, } pub fn spawn_bootstrap_peer_discovery(params: BootstrapParams) { @@ -69,8 +70,10 @@ pub fn spawn_bootstrap_peer_discovery(params: BootstrapParams) { } pub async fn bootstrap_peer_discovery(mut params: BootstrapParams) -> Result<(), String> { - set_node_mode(NodeMode::Syncing); - request_mining_stop(); + if params.run_startup_sync { + set_node_mode(NodeMode::Syncing); + request_mining_stop(); + } let (_, _, local_endpoint) = get_ip_and_port().await; let max = SETTINGS.outgoing_connections; let mut no_progress_count = 0; @@ -157,6 +160,10 @@ pub async fn bootstrap_peer_discovery(mut params: BootstrapParams) -> Result<(), } } + if !params.run_startup_sync { + return Ok(()); + } + loop { let local_height = get_height(¶ms.db); let remote_height = @@ -398,6 +405,7 @@ pub async fn process_handshake_response( db: params.db.clone(), map: params.map.clone(), first: params.first, + run_startup_sync: true, }; spawn_bootstrap_peer_discovery(bsparams); diff --git a/src/rpc/commands/address_history.rs b/src/rpc/commands/address_history.rs index 69a9e4f..602e0d4 100644 --- a/src/rpc/commands/address_history.rs +++ b/src/rpc/commands/address_history.rs @@ -19,6 +19,14 @@ fn prefix_successor(prefix: &[u8]) -> Option> { None } +fn history_bounds(address_bytes: &[u8]) -> (Bound>, Bound>) { + let start = Bound::Included(address_bytes.to_vec()); + let end = prefix_successor(address_bytes) + .map(Bound::Excluded) + .unwrap_or(Bound::Unbounded); + (start, end) +} + pub async fn lookup(address_bytes: Vec, skip: u32, limit: u32, db: &Db) -> RpcResponse { if address_bytes.len() != Wallet::SHORT_ADDRESS_BYTES_LENGTH { return RpcResponse::Binary(b"error: Invalid wallet address bytes".to_vec()); @@ -38,16 +46,13 @@ pub async fn lookup(address_bytes: Vec, skip: u32, limit: u32, db: &Db) -> R } }; - let start = Bound::Included(address_bytes.clone()); - let end = prefix_successor(&address_bytes) - .map(Bound::Excluded) - .unwrap_or(Bound::Unbounded); + let (start, end) = history_bounds(&address_bytes); let mut skipped = 0usize; let mut found = 0usize; let mut txids = Vec::with_capacity(limit * TXID_LENGTH); - for entry in tree.range((start, end)).rev() { + for entry in tree.range((start, end)) { let (_key, value) = match entry { Ok(entry) => entry, Err(err) => { @@ -77,5 +82,48 @@ pub async fn lookup(address_bytes: Vec, skip: u32, limit: u32, db: &Db) -> R } pub async fn latest(address_bytes: Vec, limit: u32, db: &Db) -> RpcResponse { - lookup(address_bytes, 0, limit, db).await + if address_bytes.len() != Wallet::SHORT_ADDRESS_BYTES_LENGTH { + return RpcResponse::Binary(b"error: Invalid wallet address bytes".to_vec()); + } + + let limit = (limit as usize).min(MAX_ADDRESS_HISTORY_TXIDS); + if limit == 0 { + return RpcResponse::Binary(Vec::new()); + } + + let tree = match db.open_tree(WALLET_TX_INDEX_TREE) { + Ok(tree) => tree, + Err(err) => { + return RpcResponse::Binary( + format!("error: Failed to open wallet transaction index: {err}").into_bytes(), + ); + } + }; + + let (start, end) = history_bounds(&address_bytes); + let mut found = 0usize; + let mut txids = Vec::with_capacity(limit * TXID_LENGTH); + + for entry in tree.range((start, end)).rev() { + let (_key, value) = match entry { + Ok(entry) => entry, + Err(err) => { + return RpcResponse::Binary( + format!("error: Failed to read wallet transaction index: {err}").into_bytes(), + ); + } + }; + + if value.len() != TXID_LENGTH { + continue; + } + + txids.extend_from_slice(&value); + found += 1; + if found >= limit { + break; + } + } + + RpcResponse::Binary(txids) }