Skip to content

Commit 40f5b4f

Browse files
feat: wallet manager integration into dash spv (#106)
* more work * fixes * work on wallet integration * fixes * wallet manager integration into dash-spv * fixes * fixes * fixes * fixes * fixes * more work
1 parent 97e9e37 commit 40f5b4f

File tree

99 files changed

+6821
-14669
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

99 files changed

+6821
-14669
lines changed

dash-spv/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ rust-version = "1.80"
1212
# Core Dash libraries
1313
dashcore = { path = "../dash", features = ["std", "serde", "core-block-hash-use-x11", "message_verification", "bls", "quorum_validation"] }
1414
dashcore_hashes = { path = "../hashes" }
15+
key-wallet-manager = { path = "../key-wallet-manager" }
1516

1617
# BLS signatures
1718
blsful = "2.5"

dash-spv/examples/filter_sync.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
//! BIP157 filter synchronization example.
22
3-
use dash_spv::{init_logging, ClientConfig, DashSpvClient, WatchItem};
3+
use dash_spv::network::MultiPeerNetworkManager;
4+
use dash_spv::storage::MemoryStorageManager;
5+
use dash_spv::{init_logging, ClientConfig, DashSpvClient};
46
use dashcore::{Address, Network};
7+
use key_wallet_manager::spv_wallet_manager::SPVWalletManager;
58
use std::str::FromStr;
9+
use std::sync::Arc;
10+
use tokio::sync::RwLock;
611

712
#[tokio::main]
813
async fn main() -> Result<(), Box<dyn std::error::Error>> {
@@ -19,8 +24,17 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
1924
.watch_address(watch_address.clone().require_network(Network::Dash).unwrap())
2025
.without_masternodes(); // Skip masternode sync for this example
2126

27+
// Create network manager
28+
let network_manager = MultiPeerNetworkManager::new(&config).await?;
29+
30+
// Create storage manager
31+
let storage_manager = MemoryStorageManager::new().await?;
32+
33+
// Create wallet manager
34+
let wallet = Arc::new(RwLock::new(SPVWalletManager::new()));
35+
2236
// Create the client
23-
let mut client = DashSpvClient::new(config).await?;
37+
let mut client = DashSpvClient::new(config, network_manager, storage_manager, wallet).await?;
2438

2539
// Start the client
2640
client.start().await?;

dash-spv/examples/reorg_demo.rs

Lines changed: 116 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,103 +1,123 @@
1+
// TODO: This example needs to be updated as the reorganize() method was removed
2+
// The reorganization logic is now handled internally by the SPV client
3+
// and wallet state is managed through the WalletInterface
4+
5+
#![allow(dead_code)]
6+
17
//! Demo showing that chain reorganization now works without borrow conflicts
28
3-
use dash_spv::chain::{ChainWork, Fork, ReorgManager};
4-
use dash_spv::storage::{MemoryStorageManager, StorageManager};
5-
use dash_spv::types::ChainState;
6-
use dash_spv::wallet::WalletState;
7-
use dashcore::{blockdata::constants::genesis_block, Header as BlockHeader, Network};
8-
use dashcore_hashes::Hash;
9-
10-
fn create_test_header(prev: &BlockHeader, nonce: u32) -> BlockHeader {
11-
let mut header = prev.clone();
12-
header.prev_blockhash = prev.block_hash();
13-
header.nonce = nonce;
14-
header.time = prev.time + 600; // 10 minutes later
15-
header
9+
// Temporarily disable this example
10+
fn main() {
11+
println!("This example is temporarily disabled pending updates to use the new architecture");
1612
}
1713

18-
#[tokio::main]
19-
async fn main() -> Result<(), Box<dyn std::error::Error>> {
20-
println!("🔧 Chain Reorganization Demo - Testing Borrow Conflict Fix\n");
21-
22-
// Create test components
23-
let network = Network::Dash;
24-
let genesis = genesis_block(network).header;
25-
let mut chain_state = ChainState::new_for_network(network);
26-
let mut wallet_state = WalletState::new(network);
27-
let mut storage = MemoryStorageManager::new().await?;
28-
29-
println!("📦 Building main chain: genesis -> block1 -> block2");
30-
31-
// Build main chain: genesis -> block1 -> block2
32-
let block1 = create_test_header(&genesis, 1);
33-
let block2 = create_test_header(&block1, 2);
34-
35-
// Store main chain
36-
storage.store_headers(&[genesis]).await?;
37-
storage.store_headers(&[block1]).await?;
38-
storage.store_headers(&[block2]).await?;
39-
40-
// Update chain state
41-
chain_state.add_header(genesis);
42-
chain_state.add_header(block1);
43-
chain_state.add_header(block2);
44-
45-
println!("✅ Main chain height: {}", chain_state.get_height());
46-
47-
println!("\n📦 Building fork: genesis -> block1' -> block2' -> block3'");
48-
49-
// Build fork chain: genesis -> block1' -> block2' -> block3'
50-
let block1_fork = create_test_header(&genesis, 100); // Different nonce
51-
let block2_fork = create_test_header(&block1_fork, 101);
52-
let block3_fork = create_test_header(&block2_fork, 102);
53-
54-
// Create fork with more work
55-
let fork = Fork {
56-
fork_point: genesis.block_hash(),
57-
fork_height: 0, // Fork from genesis
58-
tip_hash: block3_fork.block_hash(),
59-
tip_height: 3,
60-
headers: vec![block1_fork, block2_fork, block3_fork],
61-
chain_work: ChainWork::from_bytes([255u8; 32]), // Maximum work
62-
};
63-
64-
println!("✅ Fork chain height: {}", fork.tip_height);
65-
println!("✅ Fork has more work than main chain");
66-
67-
println!("\n🔄 Attempting reorganization...");
68-
println!(" This previously failed with borrow conflict!");
69-
70-
// Create reorg manager
71-
let reorg_manager = ReorgManager::new(100, false);
72-
73-
// This should now work without borrow conflicts!
74-
match reorg_manager.reorganize(&mut chain_state, &mut wallet_state, &fork, &mut storage).await {
75-
Ok(event) => {
76-
println!("\n✅ Reorganization SUCCEEDED!");
77-
println!(
78-
" - Common ancestor: {} at height {}",
79-
event.common_ancestor, event.common_height
80-
);
81-
println!(" - Disconnected {} headers", event.disconnected_headers.len());
82-
println!(" - Connected {} headers", event.connected_headers.len());
83-
println!(" - New chain height: {}", chain_state.get_height());
84-
85-
// Verify new headers were stored
86-
let header_at_3 = storage.get_header(3).await?;
87-
if header_at_3.is_some() {
88-
println!("\n✅ New chain tip verified in storage!");
89-
}
14+
#[cfg(skip_example)]
15+
mod disabled_example {
16+
use dash_spv::chain::{ChainWork, Fork, ReorgManager};
17+
use dash_spv::storage::{MemoryStorageManager, StorageManager};
18+
use dash_spv::types::ChainState;
19+
use dashcore::{blockdata::constants::genesis_block, Header as BlockHeader, Network};
20+
use dashcore_hashes::Hash;
21+
use key_wallet_manager::spv_wallet_manager::SPVWalletManager;
22+
use std::sync::Arc;
23+
use tokio::sync::RwLock;
24+
25+
fn create_test_header(prev: &BlockHeader, nonce: u32) -> BlockHeader {
26+
let mut header = prev.clone();
27+
header.prev_blockhash = prev.block_hash();
28+
header.nonce = nonce;
29+
header.time = prev.time + 600; // 10 minutes later
30+
header
31+
}
9032

91-
println!("\n🎉 Borrow conflict has been resolved!");
92-
println!(" The reorganization now uses a phased approach:");
93-
println!(" 1. Read phase: Collect all necessary data");
94-
println!(" 2. Write phase: Apply changes using only StorageManager");
95-
}
96-
Err(e) => {
97-
println!("\n❌ Reorganization failed: {}", e);
98-
println!(" This suggests the borrow conflict still exists.");
33+
#[tokio::main]
34+
async fn main() -> Result<(), Box<dyn std::error::Error>> {
35+
println!("🔧 Chain Reorganization Demo - Testing Borrow Conflict Fix\n");
36+
37+
// Create test components
38+
let network = Network::Dash;
39+
let genesis = genesis_block(network).header;
40+
let mut chain_state = ChainState::new_for_network(network);
41+
let wallet_manager = Arc::new(RwLock::new(SPVWalletManager::new()));
42+
let mut storage = MemoryStorageManager::new().await?;
43+
44+
println!("📦 Building main chain: genesis -> block1 -> block2");
45+
46+
// Build main chain: genesis -> block1 -> block2
47+
let block1 = create_test_header(&genesis, 1);
48+
let block2 = create_test_header(&block1, 2);
49+
50+
// Store main chain
51+
storage.store_headers(&[genesis]).await?;
52+
storage.store_headers(&[block1]).await?;
53+
storage.store_headers(&[block2]).await?;
54+
55+
// Update chain state
56+
chain_state.add_header(genesis);
57+
chain_state.add_header(block1);
58+
chain_state.add_header(block2);
59+
60+
println!("✅ Main chain height: {}", chain_state.get_height());
61+
62+
println!("\n📦 Building fork: genesis -> block1' -> block2' -> block3'");
63+
64+
// Build fork chain: genesis -> block1' -> block2' -> block3'
65+
let block1_fork = create_test_header(&genesis, 100); // Different nonce
66+
let block2_fork = create_test_header(&block1_fork, 101);
67+
let block3_fork = create_test_header(&block2_fork, 102);
68+
69+
// Create fork with more work
70+
let fork = Fork {
71+
fork_point: genesis.block_hash(),
72+
fork_height: 0, // Fork from genesis
73+
tip_hash: block3_fork.block_hash(),
74+
tip_height: 3,
75+
headers: vec![block1_fork, block2_fork, block3_fork],
76+
chain_work: ChainWork::from_bytes([255u8; 32]), // Maximum work
77+
};
78+
79+
println!("✅ Fork chain height: {}", fork.tip_height);
80+
println!("✅ Fork has more work than main chain");
81+
82+
println!("\n🔄 Attempting reorganization...");
83+
println!(" This previously failed with borrow conflict!");
84+
85+
// Create reorg manager
86+
let reorg_manager = ReorgManager::new(100, false);
87+
88+
// This should now work without borrow conflicts!
89+
// Note: reorganize now takes wallet as an Arc<RwLock<W>> where W: WalletInterface
90+
match reorg_manager
91+
.reorganize(&mut chain_state, wallet_manager.clone(), &fork, &mut storage)
92+
.await
93+
{
94+
Ok(event) => {
95+
println!("\n✅ Reorganization SUCCEEDED!");
96+
println!(
97+
" - Common ancestor: {} at height {}",
98+
event.common_ancestor, event.common_height
99+
);
100+
println!(" - Disconnected {} headers", event.disconnected_headers.len());
101+
println!(" - Connected {} headers", event.connected_headers.len());
102+
println!(" - New chain height: {}", chain_state.get_height());
103+
104+
// Verify new headers were stored
105+
let header_at_3 = storage.get_header(3).await?;
106+
if header_at_3.is_some() {
107+
println!("\n✅ New chain tip verified in storage!");
108+
}
109+
110+
println!("\n🎉 Borrow conflict has been resolved!");
111+
println!(" The reorganization now uses a phased approach:");
112+
println!(" 1. Read phase: Collect all necessary data");
113+
println!(" 2. Write phase: Apply changes using only StorageManager");
114+
}
115+
Err(e) => {
116+
println!("\n❌ Reorganization failed: {}", e);
117+
println!(" This suggests the borrow conflict still exists.");
118+
}
99119
}
100-
}
101120

102-
Ok(())
103-
}
121+
Ok(())
122+
}
123+
} // end of disabled_example module

dash-spv/examples/simple_sync.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
//! Simple header synchronization example.
22
3+
use dash_spv::network::MultiPeerNetworkManager;
4+
use dash_spv::storage::MemoryStorageManager;
35
use dash_spv::{init_logging, ClientConfig, DashSpvClient};
6+
use key_wallet_manager::spv_wallet_manager::SPVWalletManager;
7+
use std::sync::Arc;
8+
use tokio::sync::RwLock;
49

510
#[tokio::main]
611
async fn main() -> Result<(), Box<dyn std::error::Error>> {
@@ -12,8 +17,17 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
1217
.without_filters() // Skip filter sync for this example
1318
.without_masternodes(); // Skip masternode sync for this example
1419

20+
// Create network manager
21+
let network_manager = MultiPeerNetworkManager::new(&config).await?;
22+
23+
// Create storage manager
24+
let storage_manager = MemoryStorageManager::new().await?;
25+
26+
// Create wallet manager
27+
let wallet = Arc::new(RwLock::new(SPVWalletManager::new()));
28+
1529
// Create the client
16-
let mut client = DashSpvClient::new(config).await?;
30+
let mut client = DashSpvClient::new(config, network_manager, storage_manager, wallet).await?;
1731

1832
// Start the client
1933
client.start().await?;

dash-spv/src/bloom/builder.rs

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
33
use super::utils::{extract_pubkey_hash, outpoint_to_bytes};
44
use crate::error::SpvError;
5-
use crate::wallet::Wallet;
65
use dashcore::address::Address;
76
use dashcore::bloom::{BloomFilter, BloomFlags};
87
use dashcore::OutPoint;
@@ -93,25 +92,8 @@ impl BloomFilterBuilder {
9392
self
9493
}
9594

96-
/// Build a bloom filter from wallet state
97-
pub async fn from_wallet(wallet: &Wallet) -> Result<Self, SpvError> {
98-
let mut builder = Self::new();
99-
100-
// Add all wallet addresses
101-
let addresses = wallet.get_all_addresses().await?;
102-
builder = builder.add_addresses(addresses);
103-
104-
// Add unspent outputs
105-
let utxos = wallet.get_unspent_outputs().await?;
106-
let outpoints = utxos.into_iter().map(|utxo| utxo.outpoint);
107-
builder = builder.add_outpoints(outpoints);
108-
109-
// Set reasonable parameters based on wallet size
110-
let total_elements = builder.addresses.len() + builder.outpoints.len();
111-
builder = builder.elements(std::cmp::max(100, total_elements as u32 * 2));
112-
113-
Ok(builder)
114-
}
95+
// Removed: from_wallet - wallet functionality is now handled externally
96+
// The wallet interface doesn't expose addresses and UTXOs directly
11597

11698
/// Build the bloom filter
11799
pub fn build(self) -> Result<BloomFilter, SpvError> {

0 commit comments

Comments
 (0)