Skip to content

Commit 6f6657e

Browse files
authored
fix: maintain_gap_limit target calculation off by one (#286)
* Improve `test_gap_limit_maintenance` * fix: `maintain_gap_limit` target calculation off by one The target index was calculated incorrectly, causing one extra address to be generated. See the test added which fails without the fix.
1 parent b19d480 commit 6f6657e

File tree

1 file changed

+39
-11
lines changed

1 file changed

+39
-11
lines changed

key-wallet/src/managed_account/address_pool.rs

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -885,8 +885,8 @@ impl AddressPool {
885885
/// Generate addresses to maintain the gap limit
886886
pub fn maintain_gap_limit(&mut self, key_source: &KeySource) -> Result<Vec<Address>> {
887887
let target = match self.highest_used {
888-
None => self.gap_limit,
889-
Some(highest) => highest + self.gap_limit + 1,
888+
None => self.gap_limit - 1,
889+
Some(highest) => highest + self.gap_limit,
890890
};
891891

892892
let mut new_addresses = Vec::new();
@@ -1229,21 +1229,49 @@ mod tests {
12291229
#[test]
12301230
fn test_gap_limit_maintenance() {
12311231
let base_path = DerivationPath::from(vec![ChildNumber::from_normal_idx(0).unwrap()]);
1232-
let mut pool = AddressPool::new_without_generation(
1232+
let key_source = test_key_source();
1233+
let gap_limit = 5;
1234+
1235+
// Create pool with gap_limit addresses already generated
1236+
let mut pool = AddressPool::new(
12331237
base_path,
12341238
AddressPoolType::External,
1235-
5,
1239+
gap_limit,
12361240
Network::Testnet,
1237-
);
1238-
let key_source = test_key_source();
1241+
&key_source,
1242+
)
1243+
.unwrap();
1244+
1245+
// Verify gap_limit addresses generated, none used
1246+
assert_eq!(pool.highest_generated, Some(gap_limit - 1));
1247+
assert_eq!(pool.highest_used, None);
1248+
assert_eq!(pool.addresses.len(), gap_limit as usize);
1249+
1250+
// Calling maintain_gap_limit should not generate any new addresses when none are used
1251+
let new_addresses = pool.maintain_gap_limit(&key_source).unwrap();
1252+
assert_eq!(new_addresses.len(), 0);
1253+
assert_eq!(pool.highest_generated, Some(gap_limit - 1));
1254+
assert_eq!(pool.addresses.len(), gap_limit as usize);
1255+
1256+
// Mark address at index 0 as used
1257+
pool.mark_index_used(0);
1258+
assert_eq!(pool.highest_used, Some(0));
1259+
1260+
// Should generate exactly 1 address to maintain gap_limit unused after index 0
1261+
let new_addresses = pool.maintain_gap_limit(&key_source).unwrap();
1262+
assert_eq!(new_addresses.len(), 1);
1263+
assert_eq!(pool.highest_generated, Some(gap_limit));
1264+
assert_eq!(pool.addresses.len(), gap_limit as usize + 1);
12391265

1240-
// Generate initial addresses
1241-
pool.generate_addresses(3, &key_source, true).unwrap();
1266+
// Mark address at index 1 and 2 as used
12421267
pool.mark_index_used(1);
1268+
pool.mark_index_used(2);
12431269

1244-
// Maintain gap limit
1245-
let _new_addrs = pool.maintain_gap_limit(&key_source).unwrap();
1246-
assert!(pool.highest_generated.unwrap_or(0) >= 6); // Should have at least index 1 + gap limit 5
1270+
// Should generate exactly 2 more addresses
1271+
let new_addresses = pool.maintain_gap_limit(&key_source).unwrap();
1272+
assert_eq!(new_addresses.len(), 2);
1273+
assert_eq!(pool.highest_generated, Some(gap_limit + 2));
1274+
assert_eq!(pool.addresses.len(), gap_limit as usize + 3);
12471275
}
12481276

12491277
#[test]

0 commit comments

Comments
 (0)