From edaa54e774be0d6841e1261a015516762ac94754 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Sun, 17 Nov 2024 04:16:21 +0100 Subject: [PATCH 1/3] fixed issue on query --- .../query_dpns_contested_resources.rs | 262 ++++++++++-------- src/database/contested_names.rs | 9 +- src/database/proof_log.rs | 31 ++- src/model/proof_log_item.rs | 4 +- src/ui/tool_screens/proof_log_screen.rs | 81 +++--- 5 files changed, 222 insertions(+), 165 deletions(-) diff --git a/src/backend_task/contested_names/query_dpns_contested_resources.rs b/src/backend_task/contested_names/query_dpns_contested_resources.rs index 9d7b9a892..83bcead0c 100644 --- a/src/backend_task/contested_names/query_dpns_contested_resources.rs +++ b/src/backend_task/contested_names/query_dpns_contested_resources.rs @@ -3,6 +3,7 @@ use crate::context::AppContext; use crate::model::proof_log_item::{ProofLogItem, RequestType}; use dash_sdk::dpp::data_contract::accessors::v0::DataContractV0Getters; use dash_sdk::dpp::data_contract::document_type::accessors::DocumentTypeV0Getters; +use dash_sdk::dpp::platform_value::Value; use dash_sdk::drive::query::vote_polls_by_document_type_query::VotePollsByDocumentTypeQuery; use dash_sdk::platform::FetchMany; use dash_sdk::query_types::ContestedResource; @@ -23,28 +24,32 @@ impl AppContext { let Some(contested_index) = document_type.find_contested_index() else { return Err("No contested index on dpns domains".to_string()); }; - let query = VotePollsByDocumentTypeQuery { - contract_id: data_contract.id(), - document_type_name: document_type.name().to_string(), - index_name: contested_index.name.clone(), - start_at_value: None, - start_index_values: vec!["dash".into()], // hardcoded for dpns - end_index_values: vec![], - limit: None, - order_ascending: true, - }; - - let (contested_resources, metadata, proof) = - ContestedResource::fetch_many_with_metadata_and_proof(&sdk, query.clone(), None) + let mut start_at_value = None; + loop { + let query = VotePollsByDocumentTypeQuery { + contract_id: data_contract.id(), + document_type_name: document_type.name().to_string(), + index_name: contested_index.name.clone(), + start_at_value, + start_index_values: vec!["dash".into()], // hardcoded for dpns + end_index_values: vec![], + limit: Some(100), + order_ascending: true, + }; + + let (contested_resources) = ContestedResource::fetch_many(&sdk, query.clone()) .await .map_err(|e| { tracing::error!("error fetching contested resources: {}", e); - if let dash_sdk::Error::Proof(dash_sdk::ProofVerifierError::GroveDBError { - proof_bytes, - height, - time_ms, - error, - }) = &e + if let dash_sdk::Error::Proof( + dash_sdk::ProofVerifierError::GroveDBProofVerificationError { + proof_bytes, + path_query, + height, + time_ms, + error, + }, + ) = &e { // Encode the query using bincode let encoded_query = @@ -57,11 +62,23 @@ impl AppContext { Err(e) => return e, }; + // Encode the path_query using bincode + let verification_path_query_bytes = + match bincode::encode_to_vec(&path_query, bincode::config::standard()) + .map_err(|encode_err| { + tracing::error!("error encoding path_query: {}", encode_err); + format!("error encoding path_query: {}", encode_err) + }) { + Ok(encoded_path_query) => encoded_path_query, + Err(e) => return e, + }; + if let Err(e) = self .db .insert_proof_log_item(ProofLogItem { request_type: RequestType::GetContestedResources, request_bytes: encoded_query, + verification_path_query_bytes, height: *height, time_ms: *time_ms, proof_bytes: proof_bytes.clone(), @@ -75,107 +92,124 @@ impl AppContext { format!("error fetching contested resources: {}", e) })?; - let contested_resources_as_strings: Vec = contested_resources - .0 - .into_iter() - .map(|contested_resource| { - contested_resource - .0 - .as_str() - .expect("expected str") - .to_string() - }) - .collect(); - - let names_to_be_updated = self - .db - .insert_name_contests_as_normalized_names(contested_resources_as_strings, &self) - .map_err(|e| e.to_string())?; - - sender - .send(TaskResult::Refresh) - .await - .map_err(|e| e.to_string())?; - - // Create a semaphore with 15 permits - let semaphore = Arc::new(Semaphore::new(24)); - - let mut handles = Vec::new(); - - let handle = { - let semaphore = semaphore.clone(); - let sdk = sdk.clone(); - let sender = sender.clone(); - let self_ref = self.clone(); - - tokio::spawn(async move { - // Acquire a permit from the semaphore - let _permit: OwnedSemaphorePermit = semaphore.acquire_owned().await.unwrap(); - - match self_ref.query_dpns_ending_times(sdk, sender.clone()).await { - Ok(_) => { - // Send a refresh message if the query succeeded - sender - .send(TaskResult::Refresh) - .await - .expect("expected to send refresh"); - } - Err(e) => { - tracing::error!("error querying dpns end times: {}", e); - sender - .send(TaskResult::Error(e)) - .await - .expect("expected to send error"); - } - } - }) - }; + let contested_resources_len = contested_resources.0.len(); - handles.push(handle); - - for name in names_to_be_updated { - // Clone the semaphore, sdk, and sender for each task - let semaphore = semaphore.clone(); - let sdk = sdk.clone(); - let sender = sender.clone(); - let self_ref = self.clone(); // Assuming self is cloneable - - // Spawn each task with a permit from the semaphore - let handle = tokio::spawn(async move { - // Acquire a permit from the semaphore - let _permit: OwnedSemaphorePermit = semaphore.acquire_owned().await.unwrap(); - - // Perform the query - match self_ref - .query_dpns_vote_contenders(&name, sdk, sender.clone()) - .await - { - Ok(_) => { - // Send a refresh message if the query succeeded - sender - .send(TaskResult::Refresh) - .await - .expect("expected to send refresh"); - } - Err(e) => { - tracing::error!("error querying dpns vote contenders for {}: {}", name, e); - sender - .send(TaskResult::Error(e)) - .await - .expect("expected to send error"); + if contested_resources_len == 0 { + break; + } + + let contested_resources_as_strings: Vec = contested_resources + .0 + .into_iter() + .map(|contested_resource| { + contested_resource + .0 + .as_str() + .expect("expected str") + .to_string() + }) + .collect(); + + let last_found_name = contested_resources_as_strings.last().unwrap().clone(); + + let names_to_be_updated = self + .db + .insert_name_contests_as_normalized_names(contested_resources_as_strings, &self) + .map_err(|e| e.to_string())?; + + sender + .send(TaskResult::Refresh) + .await + .map_err(|e| e.to_string())?; + + // Create a semaphore with 15 permits + let semaphore = Arc::new(Semaphore::new(24)); + + let mut handles = Vec::new(); + + let handle = { + let semaphore = semaphore.clone(); + let sdk = sdk.clone(); + let sender = sender.clone(); + let self_ref = self.clone(); + + tokio::spawn(async move { + // Acquire a permit from the semaphore + let _permit: OwnedSemaphorePermit = semaphore.acquire_owned().await.unwrap(); + + match self_ref.query_dpns_ending_times(sdk, sender.clone()).await { + Ok(_) => { + // Send a refresh message if the query succeeded + sender + .send(TaskResult::Refresh) + .await + .expect("expected to send refresh"); + } + Err(e) => { + tracing::error!("error querying dpns end times: {}", e); + sender + .send(TaskResult::Error(e)) + .await + .expect("expected to send error"); + } } - } - }); + }) + }; - // Collect all task handles handles.push(handle); - } - // Await all tasks - for handle in handles { - if let Err(e) = handle.await { - tracing::error!("Task failed: {:?}", e); + for name in names_to_be_updated { + // Clone the semaphore, sdk, and sender for each task + let semaphore = semaphore.clone(); + let sdk = sdk.clone(); + let sender = sender.clone(); + let self_ref = self.clone(); // Assuming self is cloneable + + // Spawn each task with a permit from the semaphore + let handle = tokio::spawn(async move { + // Acquire a permit from the semaphore + let _permit: OwnedSemaphorePermit = semaphore.acquire_owned().await.unwrap(); + + // Perform the query + match self_ref + .query_dpns_vote_contenders(&name, sdk, sender.clone()) + .await + { + Ok(_) => { + // Send a refresh message if the query succeeded + sender + .send(TaskResult::Refresh) + .await + .expect("expected to send refresh"); + } + Err(e) => { + tracing::error!( + "error querying dpns vote contenders for {}: {}", + name, + e + ); + sender + .send(TaskResult::Error(e)) + .await + .expect("expected to send error"); + } + } + }); + + // Collect all task handles + handles.push(handle); + } + + // Await all tasks + for handle in handles { + if let Err(e) = handle.await { + tracing::error!("Task failed: {:?}", e); + } + } + if contested_resources_len < 100 { + break; } + start_at_value = Some((Value::Text(last_found_name), false)) } Ok(()) diff --git a/src/database/contested_names.rs b/src/database/contested_names.rs index 41e72642f..472d9d530 100644 --- a/src/database/contested_names.rs +++ b/src/database/contested_names.rs @@ -699,10 +699,11 @@ impl Database { for (name, new_ending_time) in name_contests { // Check if the name exists in the database and retrieve the current ending time let existing_ending_time: Option = - select_stmt.query_row(params![network, name], |row| { - let ending_time: Result> = row.get(0); - ending_time - })?; + match select_stmt.query_row(params![network, name], |row| row.get(0)) { + Ok(ending_time) => ending_time, + Err(rusqlite::Error::QueryReturnedNoRows) => continue, // Handle no rows case gracefully + Err(e) => return Err(e.into()), // Propagate other errors + }; if let Some(existing_ending_time) = existing_ending_time { // Update only if the new ending time is greater than the existing one diff --git a/src/database/proof_log.rs b/src/database/proof_log.rs index 42d3e718d..8a71c9237 100644 --- a/src/database/proof_log.rs +++ b/src/database/proof_log.rs @@ -4,6 +4,19 @@ use rusqlite::params; use std::ops::Range; impl Database { + pub fn drop_proof_log_table(&self) -> rusqlite::Result<()> { + // Acquire a lock on the database connection + let conn = self.conn.lock().unwrap(); + + // Execute the SQL command to drop the proof_log table + conn.execute("DROP TABLE IF EXISTS proof_log", [])?; + Ok(()) + } + + pub fn remake_proof_log_table(&self) -> rusqlite::Result<()> { + self.drop_proof_log_table()?; + self.initialize_proof_log_table() + } pub fn initialize_proof_log_table(&self) -> rusqlite::Result<()> { // Create the proof log tree self.execute( @@ -11,6 +24,7 @@ impl Database { proof_id INTEGER PRIMARY KEY AUTOINCREMENT, request_type INTEGER NOT NULL, request_bytes BLOB NOT NULL, + path_query_bytes BLOB NOT NULL, height INTEGER NOT NULL, time_ms INTEGER NOT NULL, proof_bytes BLOB NOT NULL, @@ -53,11 +67,12 @@ impl Database { let request_type_int: u8 = item.request_type.into(); conn.execute( - "INSERT INTO proof_log (request_type, request_bytes, height, time_ms, proof_bytes, error) - VALUES (?, ?, ?, ?, ?, ?)", + "INSERT INTO proof_log (request_type, request_bytes, path_query_bytes, height, time_ms, proof_bytes, error) + VALUES (?, ?, ?, ?, ?, ?, ?)", params![ request_type_int, item.request_bytes, + item.verification_path_query_bytes, item.height, item.time_ms, item.proof_bytes, @@ -78,7 +93,7 @@ impl Database { // Build the query based on the only_get_errored flag let mut query = String::from( - "SELECT request_type, request_bytes, height, time_ms, proof_bytes, error FROM proof_log", + "SELECT request_type, request_bytes, path_query_bytes, height, time_ms, proof_bytes, error FROM proof_log", ); if only_get_errored { @@ -93,10 +108,11 @@ impl Database { stmt.query_map(params![range.end - range.start, range.start], |row| { let request_type_int: u8 = row.get(0)?; let request_bytes: Vec = row.get(1)?; - let height: u64 = row.get(2)?; - let time_ms: u64 = row.get(3)?; - let proof_bytes: Vec = row.get(4)?; - let error: Option = row.get(5)?; + let verification_path_query_bytes: Vec = row.get(2)?; + let height: u64 = row.get(3)?; + let time_ms: u64 = row.get(4)?; + let proof_bytes: Vec = row.get(5)?; + let error: Option = row.get(6)?; // Convert u8 to RequestType let request_type = RequestType::try_from(request_type_int).map_err(|_| { @@ -110,6 +126,7 @@ impl Database { Ok(ProofLogItem { request_type, request_bytes, + verification_path_query_bytes, height, time_ms, proof_bytes, diff --git a/src/model/proof_log_item.rs b/src/model/proof_log_item.rs index d177b98bb..8a9cdc694 100644 --- a/src/model/proof_log_item.rs +++ b/src/model/proof_log_item.rs @@ -34,6 +34,7 @@ pub enum RequestType { GetCurrentQuorumsInfo = 32, } +use dash_sdk::drive::query::PathQuery; use std::convert::TryFrom; impl From for u8 { @@ -84,10 +85,11 @@ impl TryFrom for RequestType { } } -#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq)] pub struct ProofLogItem { pub request_type: RequestType, pub request_bytes: Vec, + pub verification_path_query_bytes: Vec, pub height: u64, pub time_ms: u64, pub proof_bytes: Vec, diff --git a/src/ui/tool_screens/proof_log_screen.rs b/src/ui/tool_screens/proof_log_screen.rs index a37ac8d6a..ce8b53d2e 100644 --- a/src/ui/tool_screens/proof_log_screen.rs +++ b/src/ui/tool_screens/proof_log_screen.rs @@ -6,6 +6,7 @@ use crate::ui::components::tools_subscreen_chooser_panel::add_tools_subscreen_ch use crate::ui::components::top_panel::add_top_panel; use crate::ui::{MessageType, RootScreenType, ScreenLike}; use dash_sdk::drive::grovedb::operations::proof::GroveDBProof; +use dash_sdk::drive::query::PathQuery; use eframe::egui::{self, Context, Grid, ScrollArea, TextEdit, Ui}; use egui::text::LayoutJob; use egui::{Color32, FontId, Frame, Stroke, TextFormat, TextStyle, Vec2}; @@ -45,6 +46,7 @@ enum ProofLogColumn { enum DisplayMode { Hex, Json, + PathQuery, } impl ProofLogScreen { @@ -248,16 +250,6 @@ impl ProofLogScreen { // Move past the hash remaining_text = &remaining_text[earliest_pos + matched_hash.len()..]; } else { - // No more hashes found, add the rest of the text - job.append( - remaining_text, - 0.0, - TextFormat { - font_id: font_id.clone(), - color: Color32::BLACK, - ..Default::default() - }, - ); break; } } @@ -271,6 +263,7 @@ impl ProofLogScreen { ui.label("Display Mode:"); ui.radio_value(&mut self.display_mode, DisplayMode::Hex, "Hex"); ui.radio_value(&mut self.display_mode, DisplayMode::Json, "JSON"); + ui.radio_value(&mut self.display_mode, DisplayMode::PathQuery, "Path Query"); }); if let Some(index) = self.selected_proof_index { @@ -284,30 +277,53 @@ impl ProofLogScreen { } else { ui.label("Error: None"); } - //display grovedb_proof info // Display proof based on display mode - let proof_display = match self.display_mode { - DisplayMode::Hex => hex::encode(&proof_item.proof_bytes), + let (proof_display, hashes) = match self.display_mode { + DisplayMode::Hex => { + let encoded = hex::encode(&proof_item.proof_bytes); + // Extract hashes from the error message + let hashes = if let Some(error) = &proof_item.error { + extract_hashes_from_error(error) + } else { + Vec::new() + }; + (encoded, hashes) + } DisplayMode::Json => { + let hashes = if let Some(error) = &proof_item.error { + extract_hashes_from_error(error) + } else { + Vec::new() + }; let config = bincode::config::standard() .with_big_endian() .with_no_limit(); let grovedb_proof: Result = bincode::decode_from_slice(&proof_item.proof_bytes, config) .map(|(a, _)| a); - match grovedb_proof { + let text = match grovedb_proof { Ok(proof) => format!("{}", proof), Err(_) => "Invalid GroveDBProof".to_string(), - } + }; + (text, hashes) + } + DisplayMode::PathQuery => { + let config = bincode::config::standard() + .with_big_endian() + .with_no_limit(); + let verification_path_query: Result = + bincode::decode_from_slice( + &proof_item.verification_path_query_bytes, + config, + ) + .map(|(a, _)| a); + let text = match verification_path_query { + Ok(path_query) => format!("{}", path_query), + Err(_) => "Invalid Path Query".to_string(), + }; + (text, vec![]) } - }; - - // Extract hashes from the error message - let hashes = if let Some(error) = &proof_item.error { - extract_hashes_from_error(error) - } else { - Vec::new() }; // Create the layout job with highlighted hashes @@ -328,23 +344,6 @@ impl ProofLogScreen { ui.label(layout_job); }); }); - - // frame.show(ui, |ui| { - // // Set the frame to the desired size - // ui.set_min_size(Vec2::new(ui.available_width() - 5.0, 300.0)); - // - // let mut binding = proof_display.clone(); - // // Remove the TextEdit's own frame and background - // let text_edit = TextEdit::multiline(&mut binding) - // .frame(false) // Remove default TextEdit frame - // .desired_width(f32::INFINITY) // Expand horizontally - // .font(egui::TextStyle::Monospace) - // .code_editor() - // .desired_rows(20); - // - // // Add the TextEdit to the UI - // ui.add(text_edit); - // }); } } else { ui.label("No proof selected."); @@ -357,6 +356,10 @@ impl ScreenLike for ProofLogScreen { // Implement message display if needed } + fn refresh_on_arrival(&mut self) { + self.fetch_proof_items() + } + /// Renders the UI components for the proof viewer screen. fn ui(&mut self, ctx: &Context) -> AppAction { let mut action = add_top_panel( From 5759b0769c520466915fc33a473dc6c0eaee7783 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Sun, 17 Nov 2024 04:45:13 +0100 Subject: [PATCH 2/3] more fixes --- src/ui/dpns_contested_names_screen.rs | 21 ++++++++++++++++- src/ui/tool_screens/proof_log_screen.rs | 30 ++++++++++++------------- 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/src/ui/dpns_contested_names_screen.rs b/src/ui/dpns_contested_names_screen.rs index 4e3892dc4..07a84438d 100644 --- a/src/ui/dpns_contested_names_screen.rs +++ b/src/ui/dpns_contested_names_screen.rs @@ -17,6 +17,7 @@ use dash_sdk::dpp::voting::vote_choices::resource_vote_choice::ResourceVoteChoic use dash_sdk::platform::Identifier; use egui::{Context, Frame, Margin, Ui}; use egui_extras::{Column, TableBuilder}; +use itertools::Itertools; use std::sync::{Arc, Mutex}; use tracing::error; @@ -323,7 +324,24 @@ impl DPNSContestedNamesScreen { locked_votes > max_contestant_votes; row.col(|ui| { - ui.label(&contested_name.normalized_contested_name); + let (used_name, highlighted) = if let Some(contestants) = &contested_name.contestants { + if let Some(first_contestant) = contestants.first() { + if contestants.iter().all(|contestant|contestant.name == first_contestant.name) { + (first_contestant.name.clone(), Some(contested_name.normalized_contested_name.clone())) + } else { + (contestants.iter().map(|contestant| contestant.name.clone()).join(" or "), + Some(contestants.iter().map(|contestant| format!("{} trying to get {}",contestant.id, contestant.name.clone())).join(" and "))) + } + } else { + (contested_name.normalized_contested_name.clone(), None) + } + } else { + (contested_name.normalized_contested_name.clone(), None) + }; + let label_response = ui.label(used_name); + if let Some(highlighted_text) = highlighted { + label_response.on_hover_text(highlighted_text); + } }); row.col(|ui| { let label_text = if let Some(locked_votes) = @@ -423,6 +441,7 @@ impl DPNSContestedNamesScreen { let contested_names = { let contested_names_guard = self.contested_names.lock().unwrap(); let mut contested_names = contested_names_guard.clone(); + contested_names.retain(|contested_name| contested_name.awarded_to.is_some()); self.sort_contested_names(&mut contested_names); contested_names }; diff --git a/src/ui/tool_screens/proof_log_screen.rs b/src/ui/tool_screens/proof_log_screen.rs index ce8b53d2e..749acb5f7 100644 --- a/src/ui/tool_screens/proof_log_screen.rs +++ b/src/ui/tool_screens/proof_log_screen.rs @@ -91,19 +91,19 @@ impl ProofLogScreen { /// Renders the left side of the screen with the list of proofs. fn render_proof_list(&mut self, ui: &mut Ui) { - ui.horizontal(|ui| { - if ui - .checkbox(&mut self.show_errors_only, "Show Errors Only") - .changed() - { - self.fetch_proof_items(); - } - ui.label("Items per page:"); - ui.add(egui::DragValue::new(&mut self.items_per_page).range(10..=1000)); - if ui.button("Refresh").clicked() { - self.fetch_proof_items(); - } - }); + // ui.horizontal(|ui| { + // if ui + // .checkbox(&mut self.show_errors_only, "Show Errors Only") + // .changed() + // { + // self.fetch_proof_items(); + // } + // ui.label("Items per page:"); + // ui.add(egui::DragValue::new(&mut self.items_per_page).range(10..=1000)); + // if ui.button("Refresh").clicked() { + // self.fetch_proof_items(); + // } + // }); // Scrollable area for the table ScrollArea::vertical() @@ -174,8 +174,8 @@ impl ProofLogScreen { // Fourth column: Error (first 20 chars, full error on hover) let error_text = item.error.as_ref().map_or("No Error".to_string(), |e| { - if e.len() > 20 { - format!("{}...", &e[..20]) + if e.len() > 40 { + format!("{}...", &e[..40]) } else { e.clone() } From 56dbe8b09f1d73307ef2cf27a1e8353dc1094d72 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Sun, 17 Nov 2024 04:54:40 +0100 Subject: [PATCH 3/3] used revision for platform --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 6a5654ddd..a49716b30 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ strum = { version = "0.26.1", features = ["derive"] } bs58 = "0.5.0" base64 = "0.22.1" copypasta = "0.10.1" -dash-sdk = { git = "https://github.com/dashpay/platform", branch = "test/testWithoutSpan2" } +dash-sdk = { git = "https://github.com/dashpay/platform", rev = "c49af53698bad1070fcfc344ccaf6b3cc404e516" } thiserror = "1" serde = "1.0.197" serde_json = "1.0.120"