|
12 | 12 | // along with this software.
|
13 | 13 | // If not, see <https://opensource.org/licenses/MIT>.
|
14 | 14 |
|
15 |
| -use std::collections::{BTreeMap, HashSet}; |
| 15 | +use std::collections::BTreeMap; |
16 | 16 | use std::convert::TryInto;
|
17 | 17 | use std::io::Seek;
|
18 | 18 | use std::path::Path;
|
19 | 19 | use std::{fs, io};
|
20 | 20 |
|
21 | 21 | use amplify::{IoError, Slice32, ToYamlString};
|
22 | 22 | use bitcoin::secp256k1::{self, Secp256k1};
|
23 |
| -use bitcoin::{Address, Amount, Script}; |
| 23 | +use bitcoin::{Address, Amount}; |
24 | 24 | use bitcoin_hd::{
|
25 | 25 | DeriveError, DescriptorDerive, SegmentIndexes, TrackingAccount,
|
26 | 26 | UnhardenedIndex,
|
@@ -164,64 +164,66 @@ impl FundingWallet {
|
164 | 164 | Ok(())
|
165 | 165 | }
|
166 | 166 |
|
167 |
| - pub fn list_funds(&self) -> Result<Vec<(AddressCompat, u64)>, Error> { |
168 |
| - let map = |(_, (script, utxo_set)): ( |
169 |
| - UnhardenedIndex, |
170 |
| - (Script, HashSet<Utxo>), |
171 |
| - )| |
172 |
| - -> Result<(AddressCompat, u64), Error> { |
173 |
| - Ok(( |
174 |
| - AddressCompat::from_script(&script, self.network) |
175 |
| - .ok_or(Error::NoAddressRepresentation)?, |
176 |
| - utxo_set |
177 |
| - .iter() |
178 |
| - .map(Utxo::amount) |
179 |
| - .copied() |
180 |
| - .map(Amount::as_sat) |
181 |
| - .sum(), |
182 |
| - )) |
183 |
| - }; |
184 |
| - |
| 167 | + /// Scans blockchain for available funds. |
| 168 | + /// Updates last derivation index basing on the scanned information. |
| 169 | + pub fn list_funds(&mut self) -> Result<Vec<(AddressCompat, u64)>, Error> { |
185 | 170 | let lookup = |case: UnhardenedIndex,
|
186 |
| - last_index: u32| |
187 |
| - -> Result<Vec<(AddressCompat, u64)>, Error> { |
| 171 | + last_index: &mut UnhardenedIndex| |
| 172 | + -> Result<Vec<_>, Error> { |
188 | 173 | self.resolver
|
189 | 174 | .resolve_descriptor_utxo(
|
190 | 175 | &self.secp,
|
191 | 176 | &self.wallet_data.descriptor,
|
192 | 177 | &[case],
|
193 | 178 | UnhardenedIndex::zero(),
|
194 |
| - last_index + 20, |
| 179 | + last_index.last_index().saturating_add(20), |
195 | 180 | )?
|
196 | 181 | .into_iter()
|
197 | 182 | .filter(|(_, (_, set))| !set.is_empty())
|
198 |
| - .map(map) |
| 183 | + // Updating last used indexes |
| 184 | + .map(|data| { |
| 185 | + if data.0 >= *last_index { |
| 186 | + *last_index = |
| 187 | + data.0.checked_inc().ok_or(Error::OutOfIndexes)?; |
| 188 | + } |
| 189 | + Ok(data) |
| 190 | + }) |
199 | 191 | .collect()
|
200 | 192 | };
|
201 | 193 |
|
202 | 194 | // Collect normal indexes
|
203 |
| - let mut funds = lookup( |
204 |
| - UnhardenedIndex::zero(), |
205 |
| - self.wallet_data.last_normal_index.last_index(), |
206 |
| - )?; |
207 |
| - funds.extend(lookup( |
208 |
| - UnhardenedIndex::one(), |
209 |
| - self.wallet_data.last_change_index.last_index(), |
210 |
| - )?); |
| 195 | + let mut last_normal_index = self.wallet_data.last_normal_index; |
| 196 | + let mut last_change_index = self.wallet_data.last_change_index; |
| 197 | + let mut funds = |
| 198 | + lookup(UnhardenedIndex::zero(), &mut last_normal_index)?; |
| 199 | + funds.extend(lookup(UnhardenedIndex::one(), &mut last_change_index)?); |
| 200 | + self.wallet_data.last_normal_index = last_normal_index; |
| 201 | + self.wallet_data.last_change_index = last_change_index; |
211 | 202 |
|
212 |
| - Ok(funds) |
| 203 | + self.save()?; |
| 204 | + |
| 205 | + funds |
| 206 | + .into_iter() |
| 207 | + .map(|(_, (script, utxo_set))| { |
| 208 | + Ok(( |
| 209 | + AddressCompat::from_script(&script, self.network) |
| 210 | + .ok_or(Error::NoAddressRepresentation)?, |
| 211 | + utxo_set |
| 212 | + .iter() |
| 213 | + .map(Utxo::amount) |
| 214 | + .copied() |
| 215 | + .map(Amount::as_sat) |
| 216 | + .sum(), |
| 217 | + )) |
| 218 | + }) |
| 219 | + .collect() |
213 | 220 | }
|
214 | 221 |
|
215 |
| - pub fn next_funding_address(&mut self) -> Result<Address, Error> { |
| 222 | + pub fn next_funding_address(&self) -> Result<Address, Error> { |
216 | 223 | let address = self.wallet_data.descriptor.address(
|
217 | 224 | &self.secp,
|
218 | 225 | &[UnhardenedIndex::zero(), self.wallet_data.last_normal_index],
|
219 | 226 | )?;
|
220 |
| - self.wallet_data |
221 |
| - .last_normal_index |
222 |
| - .checked_inc_assign() |
223 |
| - .ok_or(Error::OutOfIndexes)?; |
224 |
| - self.save()?; |
225 | 227 | Ok(address)
|
226 | 228 | }
|
227 | 229 | }
|
0 commit comments