Skip to content

chore(dash-spv): refresh masternode seed files#695

Merged
xdustinface merged 1 commit into
v0.42-devfrom
chore/refresh-masternode-seeds
Apr 28, 2026
Merged

chore(dash-spv): refresh masternode seed files#695
xdustinface merged 1 commit into
v0.42-devfrom
chore/refresh-masternode-seeds

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

Weekly automated refresh of the hardcoded masternode IP lists
embedded in dash-spv (dash-network-seeds/seeds/mainnet.txt,
dash-network-seeds/seeds/testnet.txt).

Generated by .github/workflows/update-masternode-seeds.yml
via the masternode-seeds-fetcher crate, which fetches the
current masternode list from the Dash P2P network using a
getmnlistd request against a peer discovered through DNS
seeds and the existing seed files.

@xdustinface xdustinface merged commit 1ff9057 into v0.42-dev Apr 28, 2026
2 checks passed
@xdustinface xdustinface deleted the chore/refresh-masternode-seeds branch April 28, 2026 01:37
QuantumExplorer added a commit that referenced this pull request Apr 28, 2026
* chore(dash-spv): refresh masternode seed files (#695)

Co-authored-by: QuantumExplorer <11468583+QuantumExplorer@users.noreply.github.com>

* feat: make wallet events atomic (#696)

* feat: make wallet events atomic

Reshape `WalletEvent` so each variant carries the records or context needed to persist a wallet update atomically off a single event, alongside the post-change balance.

The variant set is now:

- `TransactionReceived { wallet_id, record, balance }`. Fires when the wallet first sees an off-chain transaction.
- `TransactionStatusChanged { wallet_id, txid, context, balance }`. Fires when a known off-chain transaction has its state change. Currently fires only for InstantSend locks.
- `BlockUpdate { wallet_id, height, inserted, updated, matured, balance }`. Carries records bucketed by what happened to them in the block, plus the post-block balance.
- `SyncHeightUpdate { wallet_id, height }`. Marks a filter-batch checkpoint.

`TransactionRecord` carries `account_type` directly, identifying the owning account. `WalletInfoInterface` gains a `matured_coinbase_records` method that enumerates coinbase records crossing the maturity threshold during a height advance, populating `BlockUpdate.matured`.

The FFI groups the flattened account-discriminator fields into an `FFIAccountType` struct and renames the prior discriminant enum to `FFIAccountKind`.

* fix: record balance before bumping `block_processed_wallet_count`

Tests wait on `block_processed_wallet_count` and then read `last_confirmed`/`last_unconfirmed`. Bumping the counter before storing the balance snapshot left those reads racey. Reorder so the balance is recorded first.

Addresses CodeRabbit review comment on PR #696
#696 (comment)

* fix: place `IdentityTopUp.registration_index` in `index_secondary`

The `FFIAccountType` doc states `index_secondary` carries `registration_index` for `IdentityTopUp` and `index = 0` for variants without a meaningful primary index, matching the parallel encoding in `FFIAccountKind::from_account_type`. The `From<&AccountType>` impl wrote `registration_index` into `index` instead, breaking the documented FFI contract.

Addresses CodeRabbit review comment on PR #696
#696 (comment)

* fix: route confirmation backfills to `new_records`

`is_new` is wallet-wide (set on the first matching account, then breaks), so the per-account `else` branch can run for an account that did not previously hold the record. `confirm_transaction` backfills via `record_transaction` in that case, but the post-call record was always pushed onto `updated_records`, breaking the atomic `inserted`/`updated` contract consumed by `WalletEvent::BlockUpdate`. Capture `existed_before` per account and route to `new_records` when the record was just created.

Addresses CodeRabbit review comment on PR #696
#696 (comment)

* refactor(key-wallet-manager): extract `finalize_block_advance` helper

`process_block` and `update_last_processed_height` duplicated the entire balance-snapshot, prior-heights collection, matured-coinbase window, height advance, and per-wallet `BlockUpdate` emission. Extract the shared tail into a private `WalletManager::finalize_block_advance` helper that takes the inserted/updated maps. `update_last_processed_height` becomes a one-line call with empty maps; `process_block` keeps only its txdata loop before delegating.

* refactor: rename wallet events for clearer semantics

Rename `WalletEvent` variants and the matching FFI callbacks to past-participle names that say what happened, replacing vague "Update" suffixes:

- `TransactionReceived` -> `TransactionDetected`. "Received" implied incoming funds, but the event fires for any first-time off-chain sighting (incoming or outgoing).
- `TransactionStatusChanged` -> `TransactionInstantLocked`. The event only ever fires for an InstantSend lock applied to a known mempool tx, so name it for what it actually is. Drop the `status: TransactionContext` field and carry the `InstantLock` directly.
- `BlockUpdate` -> `BlockProcessed`. Mirrors `process_block` and matches the past-participle pattern.
- `SyncHeightUpdate` -> `SyncHeightAdvanced`. Conveys monotonic forward motion.

FFI rename mirrors the Rust side: the IS callback now takes `islock_data: *const u8` + `islock_len: usize` instead of an `FFITransactionContext`, removing a discriminant that was always `InstantSend`. The wallet-side `OnBlockProcessedCallback` becomes `OnWalletBlockProcessedCallback` to disambiguate from the existing sync-event type with the same name.

* fix: record balance before bumping IS-locked counter in test callback

Addresses CodeRabbit review comment on PR #696
#696 (review)

The instant_locked callback bumped `transaction_instant_send_locked_count` before calling `record_balance`. Tests that wait on the counter and then read `last_confirmed`/`last_unconfirmed` could observe the previous balance snapshot. Match the ordering used by the other callbacks: store the balance first, then bump the counter.

* fix: backfill missing transaction record in InstantSend path

Addresses CodeRabbit review comment on PR #696
#696 (review)

The IS-lock branch in `WalletTransactionChecker::check_core_transaction` only updated accounts that already held a `TransactionRecord` for the txid. When wallet-level `is_new` was `false` (because at least one account had the record) but another matched account did not, the latter was silently skipped: no record was created and `mark_utxos_instant_send` ran against an empty UTXO set on that account.

Mirror the confirmation path: when the affected account lacks the record, call `record_transaction` to register the record and its UTXOs, then mark them IS-locked. This ordering ensures the freshly registered UTXOs receive the IS-lock flag too. The backfilled record is pushed into `new_records` to match the existing convention from commit 659a6d5.

Add `test_instantsend_backfills_missing_record_in_other_account` covering the multi-account scenario.

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: QuantumExplorer <11468583+QuantumExplorer@users.noreply.github.com>
Co-authored-by: Kevin Rombach <35775977+xdustinface@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
QuantumExplorer added a commit that referenced this pull request Apr 28, 2026
* feat: per-wallet filter scan and runtime wallet catch-up

Filter matching and block processing now operate per wallet, so a wallet added at runtime catches up without forcing the already-synced wallets to reprocess anything.

- `WalletInterface` restructured around per-wallet ops: `process_block_for_wallets`, `wallets_behind`, `monitored_addresses_for`, `wallet_synced_height`, and monotonic per-wallet height updates. Aggregate heights are derived (min of `synced_height`, max of `last_processed_height`) rather than stored.
- `FiltersManager::scan_batch` matches each behind wallet's addresses only against filter heights it hasn't yet covered; already-synced wallets are skipped entirely. Matched blocks flow through `BlocksNeeded` carrying the per-block wallet set so `BlocksManager` processes each block only against the wallets whose filters matched. `FiltersBatch` records the scanned-wallet set so commit advances only their `synced_height`.
- `FiltersManager::tick` detects when a wallet's `synced_height` sits below the current `committed_height` (a runtime add behind scan progress), clears in-flight pipeline state, lowers `committed_height` to the new aggregate floor, and re-enters `start_download` on the next 100ms tick. Runs in `Syncing`, `Synced`, and `WaitForEvents`.

Based on:
- #689

* chore: merge v0.42-dev into feat/per-wallet-filter-scan (#698)

* chore(dash-spv): refresh masternode seed files (#695)

Co-authored-by: QuantumExplorer <11468583+QuantumExplorer@users.noreply.github.com>

* feat: make wallet events atomic (#696)

* feat: make wallet events atomic

Reshape `WalletEvent` so each variant carries the records or context needed to persist a wallet update atomically off a single event, alongside the post-change balance.

The variant set is now:

- `TransactionReceived { wallet_id, record, balance }`. Fires when the wallet first sees an off-chain transaction.
- `TransactionStatusChanged { wallet_id, txid, context, balance }`. Fires when a known off-chain transaction has its state change. Currently fires only for InstantSend locks.
- `BlockUpdate { wallet_id, height, inserted, updated, matured, balance }`. Carries records bucketed by what happened to them in the block, plus the post-block balance.
- `SyncHeightUpdate { wallet_id, height }`. Marks a filter-batch checkpoint.

`TransactionRecord` carries `account_type` directly, identifying the owning account. `WalletInfoInterface` gains a `matured_coinbase_records` method that enumerates coinbase records crossing the maturity threshold during a height advance, populating `BlockUpdate.matured`.

The FFI groups the flattened account-discriminator fields into an `FFIAccountType` struct and renames the prior discriminant enum to `FFIAccountKind`.

* fix: record balance before bumping `block_processed_wallet_count`

Tests wait on `block_processed_wallet_count` and then read `last_confirmed`/`last_unconfirmed`. Bumping the counter before storing the balance snapshot left those reads racey. Reorder so the balance is recorded first.

Addresses CodeRabbit review comment on PR #696
#696 (comment)

* fix: place `IdentityTopUp.registration_index` in `index_secondary`

The `FFIAccountType` doc states `index_secondary` carries `registration_index` for `IdentityTopUp` and `index = 0` for variants without a meaningful primary index, matching the parallel encoding in `FFIAccountKind::from_account_type`. The `From<&AccountType>` impl wrote `registration_index` into `index` instead, breaking the documented FFI contract.

Addresses CodeRabbit review comment on PR #696
#696 (comment)

* fix: route confirmation backfills to `new_records`

`is_new` is wallet-wide (set on the first matching account, then breaks), so the per-account `else` branch can run for an account that did not previously hold the record. `confirm_transaction` backfills via `record_transaction` in that case, but the post-call record was always pushed onto `updated_records`, breaking the atomic `inserted`/`updated` contract consumed by `WalletEvent::BlockUpdate`. Capture `existed_before` per account and route to `new_records` when the record was just created.

Addresses CodeRabbit review comment on PR #696
#696 (comment)

* refactor(key-wallet-manager): extract `finalize_block_advance` helper

`process_block` and `update_last_processed_height` duplicated the entire balance-snapshot, prior-heights collection, matured-coinbase window, height advance, and per-wallet `BlockUpdate` emission. Extract the shared tail into a private `WalletManager::finalize_block_advance` helper that takes the inserted/updated maps. `update_last_processed_height` becomes a one-line call with empty maps; `process_block` keeps only its txdata loop before delegating.

* refactor: rename wallet events for clearer semantics

Rename `WalletEvent` variants and the matching FFI callbacks to past-participle names that say what happened, replacing vague "Update" suffixes:

- `TransactionReceived` -> `TransactionDetected`. "Received" implied incoming funds, but the event fires for any first-time off-chain sighting (incoming or outgoing).
- `TransactionStatusChanged` -> `TransactionInstantLocked`. The event only ever fires for an InstantSend lock applied to a known mempool tx, so name it for what it actually is. Drop the `status: TransactionContext` field and carry the `InstantLock` directly.
- `BlockUpdate` -> `BlockProcessed`. Mirrors `process_block` and matches the past-participle pattern.
- `SyncHeightUpdate` -> `SyncHeightAdvanced`. Conveys monotonic forward motion.

FFI rename mirrors the Rust side: the IS callback now takes `islock_data: *const u8` + `islock_len: usize` instead of an `FFITransactionContext`, removing a discriminant that was always `InstantSend`. The wallet-side `OnBlockProcessedCallback` becomes `OnWalletBlockProcessedCallback` to disambiguate from the existing sync-event type with the same name.

* fix: record balance before bumping IS-locked counter in test callback

Addresses CodeRabbit review comment on PR #696
#696 (review)

The instant_locked callback bumped `transaction_instant_send_locked_count` before calling `record_balance`. Tests that wait on the counter and then read `last_confirmed`/`last_unconfirmed` could observe the previous balance snapshot. Match the ordering used by the other callbacks: store the balance first, then bump the counter.

* fix: backfill missing transaction record in InstantSend path

Addresses CodeRabbit review comment on PR #696
#696 (review)

The IS-lock branch in `WalletTransactionChecker::check_core_transaction` only updated accounts that already held a `TransactionRecord` for the txid. When wallet-level `is_new` was `false` (because at least one account had the record) but another matched account did not, the latter was silently skipped: no record was created and `mark_utxos_instant_send` ran against an empty UTXO set on that account.

Mirror the confirmation path: when the affected account lacks the record, call `record_transaction` to register the record and its UTXOs, then mark them IS-locked. This ordering ensures the freshly registered UTXOs receive the IS-lock flag too. The backfilled record is pushed into `new_records` to match the existing convention from commit 659a6d5.

Add `test_instantsend_backfills_missing_record_in_other_account` covering the multi-account scenario.

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: QuantumExplorer <11468583+QuantumExplorer@users.noreply.github.com>
Co-authored-by: Kevin Rombach <35775977+xdustinface@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: QuantumExplorer <quantum@dash.org>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: QuantumExplorer <11468583+QuantumExplorer@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants