Skip to content

Commit 1cf91f8

Browse files
authored
Merge branch 'main' into bump-version
2 parents 3cea6c8 + d7ac983 commit 1cf91f8

File tree

2 files changed

+51
-13
lines changed

2 files changed

+51
-13
lines changed

src/wallet/coin_store.rs

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
use std::{collections::HashMap, future::Future};
22

3-
use chia_protocol::CoinState;
3+
use chia_protocol::{Coin, CoinState};
44
use parking_lot::Mutex;
55

66
/// Keeps track of the state of coins in a wallet.
77
pub trait CoinStore {
88
/// Applies coin state updates.
99
fn update_coin_state(&self, coin_states: Vec<CoinState>) -> impl Future<Output = ()> + Send;
1010

11+
/// Gets a list of unspent coins.
12+
fn unspent_coins(&self) -> impl Future<Output = Vec<Coin>> + Send;
13+
14+
/// Gets the current state of a coin.
15+
fn coin_state(&self, coin_id: [u8; 32]) -> impl Future<Output = Option<CoinState>> + Send;
16+
1117
/// Gets coin states for a given puzzle hash.
1218
fn is_used(&self, puzzle_hash: [u8; 32]) -> impl Future<Output = bool> + Send;
1319
}
@@ -30,22 +36,41 @@ impl CoinStore for MemoryCoinStore {
3036
async fn update_coin_state(&self, coin_states: Vec<CoinState>) {
3137
for coin_state in coin_states {
3238
let puzzle_hash = &coin_state.coin.puzzle_hash;
39+
let puzzle_hash = <&[u8; 32]>::from(puzzle_hash);
40+
let mut db = self.coin_states.lock();
3341

34-
if let Some(items) = self
35-
.coin_states
36-
.lock()
37-
.get_mut(<&[u8; 32]>::from(puzzle_hash))
38-
{
42+
if let Some(items) = db.get_mut(puzzle_hash) {
3943
match items.iter_mut().find(|item| item.coin == coin_state.coin) {
4044
Some(value) => {
4145
*value = coin_state;
4246
}
4347
None => items.push(coin_state),
4448
}
49+
} else {
50+
db.insert(*puzzle_hash, vec![coin_state]);
4551
}
4652
}
4753
}
4854

55+
async fn unspent_coins(&self) -> Vec<Coin> {
56+
self.coin_states
57+
.lock()
58+
.values()
59+
.flatten()
60+
.filter(|coin_state| coin_state.spent_height.is_none())
61+
.map(|coin_state| coin_state.coin.clone())
62+
.collect()
63+
}
64+
65+
async fn coin_state(&self, coin_id: [u8; 32]) -> Option<CoinState> {
66+
self.coin_states
67+
.lock()
68+
.values()
69+
.flatten()
70+
.find(|coin_state| coin_state.coin.coin_id() == coin_id)
71+
.cloned()
72+
}
73+
4974
async fn is_used(&self, puzzle_hash: [u8; 32]) -> bool {
5075
self.coin_states
5176
.lock()

src/wallet/sync.rs

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::sync::Arc;
22

33
use chia_client::{Error, Peer, PeerEvent};
4+
use tokio::sync::mpsc;
45

56
use crate::{CoinStore, DerivationStore};
67

@@ -25,6 +26,7 @@ pub async fn incremental_sync(
2526
derivation_store: Arc<impl DerivationStore>,
2627
coin_store: Arc<impl CoinStore>,
2728
config: SyncConfig,
29+
synced_sender: mpsc::Sender<()>,
2830
) -> Result<(), Error<()>> {
2931
let mut event_receiver = peer.receiver().resubscribe();
3032

@@ -47,6 +49,8 @@ pub async fn incremental_sync(
4749
)
4850
.await?;
4951

52+
synced_sender.send(()).await.ok();
53+
5054
while let Ok(event) = event_receiver.recv().await {
5155
if let PeerEvent::CoinStateUpdate(update) = event {
5256
coin_store.update_coin_state(update.items).await;
@@ -57,13 +61,16 @@ pub async fn incremental_sync(
5761
&config,
5862
)
5963
.await?;
64+
65+
synced_sender.send(()).await.ok();
6066
}
6167
}
6268

6369
Ok(())
6470
}
6571

66-
async fn subscribe(
72+
/// Subscribe to another set of puzzle hashes.
73+
pub async fn subscribe(
6774
peer: &Peer,
6875
coin_store: &impl CoinStore,
6976
puzzle_hashes: Vec<[u8; 32]>,
@@ -75,7 +82,8 @@ async fn subscribe(
7582
Ok(())
7683
}
7784

78-
async fn derive_more(
85+
/// Create more derivations for a wallet.
86+
pub async fn derive_more(
7987
peer: &Peer,
8088
derivation_store: &impl DerivationStore,
8189
coin_store: &impl CoinStore,
@@ -93,21 +101,26 @@ async fn derive_more(
93101
subscribe(peer, coin_store, puzzle_hashes).await
94102
}
95103

96-
async fn unused_index(
104+
/// Gets the last unused derivation index for a wallet.
105+
pub async fn unused_index(
97106
derivation_store: &impl DerivationStore,
98107
coin_store: &impl CoinStore,
99108
) -> Option<u32> {
100109
let derivations = derivation_store.derivations().await;
110+
let mut unused_index = None;
101111
for index in (0..derivations).rev() {
102112
let puzzle_hash = derivation_store.puzzle_hash(index).await.unwrap();
103113
if !coin_store.is_used(puzzle_hash).await {
104-
return Some(index);
114+
unused_index = Some(index);
115+
} else {
116+
break;
105117
}
106118
}
107-
None
119+
unused_index
108120
}
109121

110-
async fn sync_to_unused_index(
122+
/// Syncs a wallet such that there are enough unused derivations.
123+
pub async fn sync_to_unused_index(
111124
peer: &Peer,
112125
derivation_store: &impl DerivationStore,
113126
coin_store: &impl CoinStore,
@@ -132,7 +145,7 @@ async fn sync_to_unused_index(
132145

133146
if let Some(unused_index) = result {
134147
// Calculate the extra unused derivations after that index.
135-
let extra_indices = derivations - 1 - unused_index;
148+
let extra_indices = derivations - unused_index;
136149

137150
// Make sure at least `gap` indices are available if needed.
138151
if extra_indices < config.minimum_unused_derivations {

0 commit comments

Comments
 (0)