Skip to content

Commit 35ff63a

Browse files
authored
Merge pull request #3 from dashpay/split_config
mainnet/testnet & timeout changes
2 parents 2cc6164 + df8eb71 commit 35ff63a

File tree

7 files changed

+95
-18
lines changed

7 files changed

+95
-18
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ tonic = { version = "0.12", features = ["tls", "tls-roots"] }
2424
prost = "0.13"
2525
tokio-stream = "0.1"
2626
semver = "1.0"
27+
chrono = "0.4"
2728

2829
[target.'cfg(not(target_os = "windows"))'.dependencies]
2930
image = "0.24"

config.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,7 @@ username = "dashrpc"
88
password = "password"
99

1010
[quorum]
11-
previous_blocks_offset = 8
11+
previous_blocks_offset = 8
12+
13+
[network]
14+
network = "testnet"

src/config.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ pub struct Config {
77
pub server: ServerConfig,
88
pub rpc: RpcConfig,
99
pub quorum: QuorumConfig,
10+
pub network: NetworkConfig,
1011
}
1112

1213
#[derive(Debug, Clone, Serialize, Deserialize)]
@@ -27,6 +28,16 @@ pub struct QuorumConfig {
2728
pub previous_blocks_offset: u32,
2829
}
2930

31+
#[derive(Debug, Clone, Serialize, Deserialize)]
32+
pub struct NetworkConfig {
33+
#[serde(default = "default_network")]
34+
pub network: String, // "mainnet" or "testnet"
35+
}
36+
37+
fn default_network() -> String {
38+
"testnet".to_string()
39+
}
40+
3041
impl Default for Config {
3142
fn default() -> Self {
3243
Self {
@@ -42,6 +53,9 @@ impl Default for Config {
4253
quorum: QuorumConfig {
4354
previous_blocks_offset: 8,
4455
},
56+
network: NetworkConfig {
57+
network: default_network(),
58+
},
4559
}
4660
}
4761
}
@@ -90,6 +104,12 @@ impl Config {
90104
}
91105
}
92106

107+
if let Ok(network) = std::env::var("DASH_NETWORK") {
108+
if network == "mainnet" || network == "testnet" {
109+
config.network.network = network;
110+
}
111+
}
112+
93113
config
94114
}
95115

@@ -98,4 +118,25 @@ impl Config {
98118
fs::write(path, content)?;
99119
Ok(())
100120
}
121+
122+
pub fn get_llmq_type(&self) -> &str {
123+
match self.network.network.as_str() {
124+
"mainnet" => "llmq_100_67",
125+
_ => "llmq_25_67", // default to testnet
126+
}
127+
}
128+
129+
pub fn get_llmq_type_id(&self) -> u32 {
130+
match self.network.network.as_str() {
131+
"mainnet" => 4, // llmq_100_67 = type 4
132+
_ => 6, // llmq_25_67 = type 6 (testnet)
133+
}
134+
}
135+
136+
pub fn get_dapi_port(&self) -> u16 {
137+
match self.network.network.as_str() {
138+
"mainnet" => 443,
139+
_ => 1443, // default to testnet
140+
}
141+
}
101142
}

src/grpc_client.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ pub async fn check_node_version(address: &str, port: u16) -> Result<VersionCheck
2727

2828
let channel = Channel::from_shared(endpoint)?
2929
.tls_config(tls)?
30-
.timeout(Duration::from_secs(5))
30+
.timeout(Duration::from_secs(2))
31+
.connect_timeout(Duration::from_secs(2))
3132
.connect()
3233
.await?;
3334

@@ -41,7 +42,7 @@ pub async fn check_node_version(address: &str, port: u16) -> Result<VersionCheck
4142

4243
// Make the request with a timeout
4344
let response = tokio::time::timeout(
44-
Duration::from_secs(5),
45+
Duration::from_secs(2),
4546
client.get_status(request)
4647
).await??;
4748

src/main.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
2323
println!("Configuration loaded:");
2424
println!(" Server: {}:{}", config.server.host, config.server.port);
2525
println!(" RPC: {} (user: {})", config.rpc.url, config.rpc.username);
26+
println!(" Network: {}", config.network.network);
27+
println!(" LLMQ Type: {} (ID: {})", config.get_llmq_type(), config.get_llmq_type_id());
28+
println!(" DAPI Port: {}", config.get_dapi_port());
2629
println!(" Previous blocks offset: {}", config.quorum.previous_blocks_offset);
2730

2831
// Load initial quorums from Dash Core
@@ -43,6 +46,17 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
4346
// Create masternode cache
4447
let masternode_cache = Arc::new(MasternodeCache::new(config.clone()));
4548

49+
// Populate masternode cache on startup
50+
println!("Loading initial masternode list...");
51+
match masternode_cache.get_masternodes().await {
52+
Ok(masternodes) => {
53+
println!("Successfully loaded {} masternodes into cache", masternodes.len());
54+
}
55+
Err(e) => {
56+
eprintln!("Warning: Failed to load initial masternodes: {}. Cache will populate on first request.", e);
57+
}
58+
}
59+
4660
// Start background refresh for masternode cache
4761
masternode_cache.clone().start_background_refresh().await;
4862

src/masternode_cache.rs

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::grpc_client;
55
use std::sync::{Arc, RwLock};
66
use std::time::{Duration, Instant};
77
use tokio::sync::Mutex;
8+
use chrono::Local;
89

910
pub struct MasternodeCache {
1011
data: Arc<RwLock<Option<EvoMasternodeList>>>,
@@ -72,21 +73,28 @@ impl MasternodeCache {
7273
async move {
7374
// Skip POSE_BANNED nodes
7475
if status == "POSE_BANNED" {
76+
println!("⏭️ Node {} at {} - skipping (POSE_BANNED)", idx, address);
7577
return (idx, "fail".to_string(), None, None);
7678
}
7779

7880
// Parse address to get IP and port
7981
let parts: Vec<&str> = address.split(':').collect();
8082
if parts.len() != 2 {
83+
println!("❌ Node {} at {} - invalid address format", idx, address);
8184
return (idx, "fail".to_string(), None, None);
8285
}
8386

8487
let ip = parts[0];
85-
let port = 1443u16; // Platform gRPC port is always 1443
88+
let port = self.config.get_dapi_port();
8689

87-
// Check version with timeout
88-
match grpc_client::check_node_version(ip, port).await {
89-
Ok(result) => {
90+
println!("🔍 Node {} at {} - checking version...", idx, address);
91+
92+
// Check version with additional timeout wrapper (3 seconds total)
93+
match tokio::time::timeout(
94+
tokio::time::Duration::from_secs(3),
95+
grpc_client::check_node_version(ip, port)
96+
).await {
97+
Ok(Ok(result)) => {
9098
if result.success {
9199
println!("✓ Node {} at {} - version 2.0+ (DAPI: {:?}, Drive: {:?})",
92100
idx, address, result.dapi_version, result.drive_version);
@@ -97,10 +105,14 @@ impl MasternodeCache {
97105
(idx, "fail".to_string(), result.dapi_version, result.drive_version)
98106
}
99107
},
100-
Err(e) => {
108+
Ok(Err(e)) => {
101109
println!("✗ Node {} at {} - error: {}", idx, address, e);
102110
(idx, "fail".to_string(), None, None)
103111
},
112+
Err(_) => {
113+
println!("✗ Node {} at {} - timeout after 3 seconds", idx, address);
114+
(idx, "fail".to_string(), None, None)
115+
},
104116
}
105117
}
106118
}).collect();
@@ -140,8 +152,11 @@ impl MasternodeCache {
140152
tokio::spawn(async move {
141153
loop {
142154
tokio::time::sleep(self.update_interval).await;
143-
if let Err(e) = self.update_cache().await {
144-
eprintln!("Failed to update masternode cache: {}", e);
155+
let now = Local::now();
156+
println!("🔄 [{}] Background refresh: Starting masternode cache update...", now.format("%Y-%m-%d %H:%M:%S"));
157+
match self.update_cache().await {
158+
Ok(_) => println!("✅ [{}] Background refresh: Masternode cache updated successfully", Local::now().format("%Y-%m-%d %H:%M:%S")),
159+
Err(e) => eprintln!("❌ [{}] Background refresh: Failed to update masternode cache: {}", Local::now().format("%Y-%m-%d %H:%M:%S"), e),
145160
}
146161
}
147162
});

src/quorum_loader.rs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,11 @@ pub async fn load_initial_quorums(
2727

2828
let mut quorum_list = QuorumList::new();
2929

30-
// Parse the extended quorum list - extract llmq_25_67 quorums for testnet
30+
// Parse the extended quorum list - extract the appropriate LLMQ type based on network
31+
let llmq_type = config.get_llmq_type();
3132
if let Some(quorum_obj) = result.as_object() {
32-
if let Some(llmq_25_67) = quorum_obj.get("llmq_25_67") {
33-
if let Some(quorums_arr) = llmq_25_67.as_array() {
33+
if let Some(llmq_quorums) = quorum_obj.get(llmq_type) {
34+
if let Some(quorums_arr) = llmq_quorums.as_array() {
3435
for quorum_item in quorums_arr {
3536
if let Some(quorum_obj) = quorum_item.as_object() {
3637
for (quorum_hash_str, quorum_info) in quorum_obj {
@@ -40,7 +41,7 @@ pub async fn load_initial_quorums(
4041
// Get the actual quorum public key via quorum info
4142
let rpc_params = [
4243
serde_json::json!("info"),
43-
serde_json::json!(6), // llmq_25_67 = type 6
44+
serde_json::json!(config.get_llmq_type_id()),
4445
serde_json::json!(quorum_hash_str)
4546
];
4647
println!("DEBUG: Calling quorum with params: {:?}", rpc_params);
@@ -113,10 +114,11 @@ pub async fn load_quorums_at_height(
113114

114115
let mut quorum_list = QuorumList::new();
115116

116-
// Parse the extended quorum list - extract llmq_25_67 quorums for testnet
117+
// Parse the extended quorum list - extract the appropriate LLMQ type based on network
118+
let llmq_type = config.get_llmq_type();
117119
if let Some(quorum_obj) = result.as_object() {
118-
if let Some(llmq_25_67) = quorum_obj.get("llmq_25_67") {
119-
if let Some(quorums_arr) = llmq_25_67.as_array() {
120+
if let Some(llmq_quorums) = quorum_obj.get(llmq_type) {
121+
if let Some(quorums_arr) = llmq_quorums.as_array() {
120122
for quorum_item in quorums_arr {
121123
if let Some(quorum_obj) = quorum_item.as_object() {
122124
for (quorum_hash_str, quorum_info) in quorum_obj {
@@ -126,7 +128,7 @@ pub async fn load_quorums_at_height(
126128
// Get the actual quorum public key via quorum info
127129
let rpc_params = [
128130
serde_json::json!("info"),
129-
serde_json::json!(6), // llmq_25_67 = type 6
131+
serde_json::json!(config.get_llmq_type_id()),
130132
serde_json::json!(quorum_hash_str),
131133
serde_json::json!(true) // includeSkShare
132134
];

0 commit comments

Comments
 (0)