Skip to content

refactor: rename Dash network entries to Mainnet#500

Open
xdustinface wants to merge 1 commit intov0.42-devfrom
fix/dash-mainnet
Open

refactor: rename Dash network entries to Mainnet#500
xdustinface wants to merge 1 commit intov0.42-devfrom
fix/dash-mainnet

Conversation

@xdustinface
Copy link
Collaborator

@xdustinface xdustinface commented Mar 7, 2026

Align the network names with Dash Core. Finally! This bugged me since i started to work on this repo haha.

Based on:

Summary by CodeRabbit

  • Refactor

    • Renamed the primary network identifier from "Dash" to "Mainnet" across the SDK and FFI surfaces.
  • Bug Fixes

    • Default network fallback for null/unspecified inputs now returns Mainnet instead of the previous identifier.
  • Documentation

    • Updated docs and examples to list and display "Mainnet" where the main network is referenced.
  • Tests

    • Updated all test suites to align with the Mainnet identifier.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 7, 2026

📝 Walkthrough

Walkthrough

This PR renames the main network enum variant from "Dash" to "Mainnet" across multiple crates (dash, dash-spv, key-wallet, FFI), updates related constants, conversions, defaults, docs, examples, and many tests. No public function signatures were changed.

Changes

Cohort / File(s) Summary
Core Network Enum & Constants
dash/src/network/constants.rs
Renamed Network::DashNetwork::Mainnet; updated magic, genesis hash, activation height, Display/FromStr and related mappings.
Address, Crypto & Consensus
dash/src/address.rs, dash/src/crypto/..., dash/src/consensus/params.rs, dash/src/blockdata/...
Replaced Dash variant with Mainnet across address parsing/formatting, WIF/version-byte mappings, bech32 prefixes, tests, and consensus params.
SML / Masternode / LLMQ
dash/src/sml/...
LLMQ type matching, masternode list logic, activation-height checks and tests updated to use Network::Mainnet.
Dash SPV Library & CLI
dash-spv/src/..., dash-spv-ffi/src/bin/ffi_cli.rs, dash-spv-ffi/src/platform_integration.rs
Default network, checkpoint selection, CLI network mapping, and platform activation-height match arms changed from Dash → Mainnet; tests updated.
Network Discovery & Messages
dash-spv/src/network/discovery.rs, dash/src/network/message.rs, dash/examples/handshake.rs
DNS discovery match arm, RawNetworkMessage magic fields, and example handshake messages updated to Mainnet; unknown-network early return added in discovery.
FFI: dash-spv-ffi
dash-spv-ffi/include/..., dash-spv-ffi/FFI_API.md, dash-spv-ffi/src/config.rs, dash-spv-ffi/tests/*
FFI docs and safety notes updated; dash_spv_ffi_config_get_network default for null config now documented/returned as FFINetwork::Mainnet; CLI/test expectations aligned.
FFI: key-wallet-ffi
key-wallet-ffi/include/key_wallet_ffi.h, key-wallet-ffi/src/types.rs, key-wallet-ffi/src/*.rs, key-wallet-ffi/FFI_API.md
FFINetwork variant DASHMAINNET (same discriminant); conversions, null-account defaults, wallet-manager fallback and tests changed to Mainnet; docs updated.
Key Wallet Core (lib)
key-wallet/src/...
Derivation paths, bip32/bip38/slip10 encodings, default network values, coin_type and MAINNET constants, address pools, and many tests switched from Dash → Mainnet; added InvalidNetwork handling in some branches.
Tests & Examples across Repos
dash-spv/tests/*, dash/tests/*, key-wallet/tests/*, dash/examples/*, key-wallet/examples/*
Wide test and example updates: all references using Dash as mainnet now use Mainnet; expected strings/address prefixes adjusted accordingly.
Fuzz & Scripts
fuzz/fuzz_targets/dash/deserialize_script.rs, dash-spv-ffi/scripts/generate_ffi_docs.py
Fuzz address checks and generated FFI docs enumeration wording updated to list Mainnet instead of Dash.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 A rabbit hops to shout and sing,
Dash is now Mainnet — what a spring!
Tests rebloom, docs hop in line,
Enums renamed, the tree looks fine.
Cheers to tidy names and code that gleams!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and accurately describes the main change: renaming the Dash network variant to Mainnet across the codebase.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/dash-mainnet

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link

codecov bot commented Mar 7, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 63.07%. Comparing base (8bca47d) to head (faa0edd).
⚠️ Report is 2 commits behind head on v0.42-dev.

Additional details and impacted files
@@              Coverage Diff              @@
##           v0.42-dev     #500      +/-   ##
=============================================
- Coverage      66.86%   63.07%   -3.80%     
=============================================
  Files            313      313              
  Lines          64756    64495     -261     
=============================================
- Hits           43299    40679    -2620     
- Misses         21457    23816    +2359     
Flag Coverage Δ *Carryforward flag
core ?
dash-network 74.91% <ø> (-0.02%) ⬇️ Carriedforward from 8bca47d
dash-network-ffi 34.76% <ø> (+0.02%) ⬆️ Carriedforward from 8bca47d
dash-spv 68.27% <ø> (-0.02%) ⬇️ Carriedforward from 8bca47d
dash-spv-ffi 34.76% <ø> (+0.02%) ⬆️ Carriedforward from 8bca47d
dashcore 74.91% <ø> (-0.02%) ⬇️ Carriedforward from 8bca47d
dashcore-private 74.91% <ø> (-0.02%) ⬇️ Carriedforward from 8bca47d
dashcore-rpc 19.92% <ø> (ø) Carriedforward from 8bca47d
dashcore-rpc-json 19.92% <ø> (ø) Carriedforward from 8bca47d
dashcore_hashes 74.91% <ø> (-0.02%) ⬇️ Carriedforward from 8bca47d
ffi ?
key-wallet 65.65% <ø> (-0.05%) ⬇️ Carriedforward from 8bca47d
key-wallet-ffi 34.76% <ø> (+0.02%) ⬆️ Carriedforward from 8bca47d
key-wallet-manager 65.65% <ø> (-0.05%) ⬇️ Carriedforward from 8bca47d
rpc ?
spv ?
wallet ?

*This pull request uses carry forward flags. Click here to find out more.

Files with missing lines Coverage Δ
dash-spv-ffi/src/bin/ffi_cli.rs 0.00% <ø> (ø)
dash-spv-ffi/src/config.rs 51.89% <ø> (-9.61%) ⬇️
dash-spv-ffi/src/platform_integration.rs 23.36% <ø> (+0.63%) ⬆️
dash-spv/src/chain/chain_work.rs 77.69% <ø> (-0.18%) ⬇️
dash-spv/src/client/config.rs 92.30% <ø> (-0.15%) ⬇️
dash-spv/src/client/config_test.rs 100.00% <ø> (ø)
dash-spv/src/client/lifecycle.rs 55.33% <ø> (-8.13%) ⬇️
dash-spv/src/main.rs 0.00% <ø> (ø)
dash-spv/src/mempool_filter.rs 84.19% <ø> (-0.46%) ⬇️
dash-spv/src/network/discovery.rs 30.76% <ø> (+0.91%) ⬆️
... and 28 more

... and 49 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@xdustinface xdustinface force-pushed the fix/dash-mainnet branch 2 times, most recently from 99debb8 to 864ab58 Compare March 7, 2026 03:10
@xdustinface xdustinface force-pushed the chore/fix-network-docs branch from b8a8fc5 to 11c5fdb Compare March 10, 2026 01:37
@github-actions
Copy link

This PR has merge conflicts with the base branch. Please rebase or merge the base branch into your branch to resolve them.

@github-actions github-actions bot added the merge-conflict The PR conflicts with the target branch. label Mar 10, 2026
Base automatically changed from chore/fix-network-docs to v0.42-dev March 10, 2026 17:09
@xdustinface xdustinface marked this pull request as ready for review March 10, 2026 17:12
@xdustinface xdustinface requested a review from ZocoLini March 10, 2026 17:12
@github-actions github-actions bot removed the merge-conflict The PR conflicts with the target branch. label Mar 10, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
key-wallet/src/derivation.rs (2)

137-153: ⚠️ Potential issue | 🟠 Major

Propagate invalid identity indexes instead of panicking.

from_hardened_idx rejects values >= 2^31. These two unwrap() calls make a fallible library API panic on bad input even though the method already returns Result<_>.

Suggested fix
         // Convert to DerivationPath and append indices
         let mut full_path = crate::bip32::DerivationPath::from(path);
-        full_path.push(crate::bip32::ChildNumber::from_hardened_idx(identity_index).unwrap());
-        full_path.push(crate::bip32::ChildNumber::from_hardened_idx(key_index).unwrap());
+        full_path.push(
+            crate::bip32::ChildNumber::from_hardened_idx(identity_index)
+                .map_err(|e| Error::InvalidDerivationPath(e.to_string()))?,
+        );
+        full_path.push(
+            crate::bip32::ChildNumber::from_hardened_idx(key_index)
+                .map_err(|e| Error::InvalidDerivationPath(e.to_string()))?,
+        );
 
         self.derive(&full_path)
     }

As per coding guidelines, "Avoid unwrap() and expect() in library code; use proper error types (e.g., thiserror)" and "Use the ? operator for error propagation, provide context in error messages, never panic in library code, and return Result<T> for all fallible operations".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@key-wallet/src/derivation.rs` around lines 137 - 153, The two unwrap() calls
in identity_authentication_key cause panics when from_hardened_idx fails for
values >= 2^31; replace them with fallible handling by calling
from_hardened_idx(...) and using the ? operator (or map_err to a suitable
crate::Error variant) to propagate the error instead of panicking, e.g. map the
child-number error into a new or existing Error variant (e.g., InvalidChildIndex
or similar) so full_path construction returns Err on bad identity_index or
key_index rather than panic.

331-350: ⚠️ Potential issue | 🟠 Major

Don't silently fall back to mainnet coin type for unknown networks.

The _ => 5 branch derives mainnet paths for any network variant that is not explicitly listed, which can mix networks silently. This helper already returns Result<_>, so unsupported networks should fail the same way the other derivation helpers do.

Suggested fix
         let coin_type = match network {
             Network::Mainnet => 5,
             Network::Testnet | Network::Devnet | Network::Regtest => 1,
-            _ => 5, // Default to Dash
+            _ => return Err(Error::InvalidNetwork),
         };

As per coding guidelines, "Always validate network consistency when deriving or validating addresses; never mix mainnet and testnet operations".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@key-wallet/src/derivation.rs` around lines 331 - 350, The match in
for_network_and_type currently uses a catch-all `_ => 5` which silently treats
unknown Network variants as mainnet; change it so the code returns an error for
unsupported networks instead of defaulting to coin_type 5. Update the coin_type
match in for_network_and_type to only handle Network::Mainnet and the explicit
test variants and make the default arm return an Err (e.g., an error indicating
Unsupported network) so the function's Result<DerivationPath> fails for unknown
networks; reference the for_network_and_type method and the Network enum when
making this change.
key-wallet-ffi/src/derivation_tests.rs (1)

587-591: ⚠️ Potential issue | 🟡 Minor

Add null checks before converting C string pointers at lines 587–591.

derivation_xpriv_to_string can return null on error (see test_derivation_xpriv_to_string_null_input), and passing null to CStr::from_ptr causes undefined behavior. The code must check both pointers before conversion, matching the safe pattern used elsewhere in this file.

Suggested fix
         let main_str = unsafe { derivation_xpriv_to_string(xprv_main, &mut error) };
         let test_str = unsafe { derivation_xpriv_to_string(xprv_test, &mut error) };
+        assert!(!main_str.is_null());
+        assert!(!test_str.is_null());

         let main_string = unsafe { CStr::from_ptr(main_str) }.to_str().unwrap();
         let test_string = unsafe { CStr::from_ptr(test_str) }.to_str().unwrap();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@key-wallet-ffi/src/derivation_tests.rs` around lines 587 - 591,
derivation_xpriv_to_string may return null, so before calling CStr::from_ptr on
main_str and test_str you must null-check both pointers (main_str and test_str)
and handle the error path similarly to other tests in this file: if either is
null, read/format the error from the existing error variable and fail the test
(or return) rather than calling CStr::from_ptr; only convert to &CStr and call
to_str().unwrap() when the pointer is non-null. Ensure you reference the same
error reporting logic used elsewhere so the test mirrors the safe pattern.
key-wallet/src/account/account_type.rs (1)

259-264: ⚠️ Potential issue | 🟠 Major

Reject unsupported networks before computing coin_type.

This still coerces any non-Mainnet input to coin type 1, so Standard, CoinJoin, and provider-key derivations can silently fall back to testnet while the identity/platform branches below now return InvalidNetwork. Please make this branch explicit so all derivation paths fail consistently on unsupported networks.

🔧 Suggested fix
-        let coin_type = if network == Network::Mainnet {
-            5
-        } else {
-            1
-        };
+        let coin_type = match network {
+            Network::Mainnet => 5,
+            Network::Testnet | Network::Devnet | Network::Regtest => 1,
+            _ => return Err(crate::error::Error::InvalidNetwork),
+        };
As per coding guidelines, "Always validate network consistency when deriving or validating addresses; never mix mainnet and testnet operations".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@key-wallet/src/account/account_type.rs` around lines 259 - 264, In
derivation_path ensure you explicitly validate Network instead of coercing
non-Mainnet to coin_type 1; update the coin_type logic in
derivation_path(Network) to match on Network (e.g., Network::Mainnet =>
coin_type = 5, Network::Testnet => coin_type = 1) and return
Err(crate::error::Error::InvalidNetwork) for any other/unsupported variants so
Standard, CoinJoin and provider-key branches don't silently fall back to
testnet; reference derivation_path, Network, coin_type, and
crate::error::Error::InvalidNetwork when making the change.
🧹 Nitpick comments (5)
dash-spv/tests/transaction_calculation_test.rs (1)

20-23: Add a testnet variant for these regression cases.

After switching these checks to Network::Mainnet, this file no longer exercises the same address-parsing/require_network path on testnet. A small parameterized companion case would keep the regression aligned with the repo rule to cover both networks in test code.

As per coding guidelines "Test both mainnet and testnet configurations".

Also applies to: 122-125, 180-183, 213-216, 233-236

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@dash-spv/tests/transaction_calculation_test.rs` around lines 20 - 23, The
test hardcodes Address::from_str(...).require_network(Network::Mainnet) which
skips exercising the testnet path; change the failing single-case to a
parameterized companion (or loop) that runs the same assertions for both
Network::Mainnet and Network::Testnet by deriving watched_address for each
network using Address::from_str(...).require_network(network) and reusing the
same test logic; apply the same pattern to the other occurrences that were
switched to Mainnet (the other Address::from_str(...).require_network(...) sites
mentioned) so each regression case runs against both networks.
dash-spv/tests/handshake_test.rs (1)

16-17: Add a testnet path to this handshake suite.

These updates keep the coverage mainnet-only, so the renamed network path is never exercised against the testnet branch in this network-focused test file. Please add a small Network::Testnet variant or parameterize the applicable tests over both networks.

As per coding guidelines, **/*test*.rs: Test both mainnet and testnet configurations.

Also applies to: 57-58, 76-77, 89-89

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@dash-spv/tests/handshake_test.rs` around lines 16 - 17, The tests in
handshake_test.rs only exercise Peer::connect with Network::Mainnet; add a
Testnet path by parameterizing the tests or duplicating the calls to cover
Network::Testnet as well. Update each call site using Peer::connect(peer_addr,
10, Network::Mainnet) (and the other occurrences around the file) to loop over
or table-drive both Network::Mainnet and Network::Testnet so the handshake suite
runs for both networks, or add equivalent assertions for Network::Testnet;
ensure you reference Network::Testnet in the same test functions that currently
use Network::Mainnet (including the sites noted at the other ranges) so both
variants are executed by the test runner.
dash-spv-ffi/src/config.rs (1)

116-122: Source the default port from shared network constants.

This FFI path still duplicates per-network P2P ports inline. With the network rename touching these mappings again, it is easy for this table to drift from the canonical network constants over time. Please route this through a shared network→default-port helper or existing network constants instead of hardcoded literals.

As per coding guidelines, **/*.rs: Never hardcode network parameters, addresses, or keys in Rust code.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@dash-spv-ffi/src/config.rs` around lines 116 - 122, The default_port binding
currently hardcodes per-network P2P ports against cfg.network; replace this
literal table with a call into the shared network constants/helper (e.g. use a
function like network::default_p2p_port(cfg.network) or
shared::network::p2p_port_for(cfg.network)) so the value is sourced from the
canonical network constants instead of inline numbers; update the code that sets
default_port (the let default_port = ... expression) to call that shared helper
and remove the hardcoded match arms.
dash-spv/src/network/tests.rs (1)

10-17: Cover the testnet constructor path here as well.

This rename is network-specific, but test_peer_creation now only exercises Network::Mainnet, so a regression in the testnet branch would still pass unnoticed.

🧪 Suggested expansion
-        let peer = Peer::new(addr, timeout, Network::Mainnet);
-
-        assert!(!peer.is_connected());
-        assert_eq!(peer.address(), addr);
+        for network in [Network::Mainnet, Network::Testnet] {
+            let peer = Peer::new(addr, timeout, network);
+            assert!(!peer.is_connected());
+            assert_eq!(peer.address(), addr);
+        }
As per coding guidelines, "`**/*test*.rs`: Test both mainnet and testnet configurations".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@dash-spv/src/network/tests.rs` around lines 10 - 17, The test_peer_creation
only constructs a Peer with Network::Mainnet; add a second assertion path that
constructs a Peer using Peer::new(addr, timeout, Network::Testnet) and verifies
the same properties (not connected and address matches) so both network variants
are covered; update the test_peer_creation function to create two peers (one
with Network::Mainnet and one with Network::Testnet) and assert is_connected()
is false and address() equals addr for each.
dash-spv/tests/test_handshake_logic.rs (1)

8-16: Add a testnet case for the handshake constructor path.

This file still only exercises Network::Mainnet, even though HandshakeManager::new(...) is network-parameterized. Please add a Testnet variant here as well, or table-drive the test over both networks.

Suggested test shape
 #[test]
 fn test_handshake_state_transitions() {
-    let mut handshake = HandshakeManager::new(Network::Mainnet, MempoolStrategy::BloomFilter, None);
-
-    // Initial state should be Init
-    assert_eq!(*handshake.state(), HandshakeState::Init);
-
-    // After reset, should be back to Init
-    handshake.reset();
-    assert_eq!(*handshake.state(), HandshakeState::Init);
+    for network in [Network::Mainnet, Network::Testnet] {
+        let mut handshake =
+            HandshakeManager::new(network, MempoolStrategy::BloomFilter, None);
+
+        assert_eq!(*handshake.state(), HandshakeState::Init);
+        handshake.reset();
+        assert_eq!(*handshake.state(), HandshakeState::Init);
+    }
 }

As per coding guidelines, Test both mainnet and testnet configurations.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@dash-spv/tests/test_handshake_logic.rs` around lines 8 - 16, The test
currently only constructs HandshakeManager with Network::Mainnet; add coverage
for Network::Testnet by either duplicating the assertions with a second instance
(e.g., let mut handshake = HandshakeManager::new(Network::Testnet,
MempoolStrategy::BloomFilter, None)) or convert test_handshake_state_transitions
into a table-driven loop that iterates over [Network::Mainnet,
Network::Testnet], creating a HandshakeManager for each and asserting initial
state is HandshakeState::Init and that reset() returns it to Init; reference the
HandshakeManager::new constructor, the Network enum (Testnet), state() and
reset() methods when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@dash-spv-ffi/FFI_API.md`:
- Around line 244-247: The generated FFI docs are inconsistent: the enum was
renamed but references to FFINetwork and its variants are stale. Regenerate the
API docs from the updated headers/comments (the sources that define
FFIClientConfig and the network enum) so all occurrences of the enum, its
variants, and the Get-network description (which mentions defaulting to
FFINetwork::Mainnet) are updated consistently across the file; search for
symbols FFINetwork and FFIClientConfig in the source headers, run the doc
generator, and verify the produced FFI_API.md contains the updated enum name and
variant list everywhere.

In `@dash-spv-ffi/src/platform_integration.rs`:
- Around line 184-190: The activation heights are hardcoded here in the local
match (variable height) and drift from the authoritative values in
dash/src/sml/llmq_type/network.rs; replace this local match with a call to the
shared helper/constant exported from that module (e.g. a public function like
get_activation_height(network: dashcore::Network) or a public constant
map/lookup such as ACTIVATION_HEIGHTS.get(network)). Import the symbol from
dash::sml::llmq_type::network, remove the duplicate match in
platform_integration.rs, and set height by calling the shared helper so Devnet
and other networks use the single source of truth. Ensure the used helper
returns the same types and semantics (Devnet -> 1 or “active immediately”) as
the core module.

In `@dash-spv/src/network/discovery.rs`:
- Around line 34-36: The match in discovery.rs that sets (seeds, port) currently
hardcodes ports (9999/19999) in the Network::Mainnet/Testnet arms; update it to
fetch the port from the centralized network parameters instead of inlining
numbers—use the shared Network params API (e.g., a port getter on the Network
enum or the global network params constant) when constructing (seeds, port) so
MAINNET_DNS_SEEDS and TESTNET_DNS_SEEDS remain paired with their canonical port
from the shared config rather than hardcoded literals.

In `@dash/examples/handshake.rs`:
- Around line 32-35: The example hardcodes Network::Mainnet.magic() when
constructing RawNetworkMessage (e.g., the first_message and the later message
around line 53); instead, add a network selection variable in main() (e.g., let
network = /* choose Network from args or env */) and thread that variable into
both message constructions by using network.magic() rather than
Network::Mainnet.magic(), ensuring both messages use the same selected Network
and updating any downstream uses that assumed Mainnet.

In `@dash/src/address.rs`:
- Around line 1002-1006: The bech32 HRP for Testnet/Devnet is inconsistent
between fmt_internal() and Address::from_str(): fmt_internal() emits "tb" while
parsing expects "td", breaking round-trips; update the bech32_hrp selection in
the formatting path (the bech32_hrp match that calls self.network()) to use the
same HRP string used by Address::from_str() for Network::Testnet and
Network::Devnet (and mirror the same change where the duplicate match appears
around the other occurrence), ensuring both formatting and parsing use the
identical HRP for each Network variant.
- Around line 1595-1597: The test currently sets key.compressed = false then
asserts Address::p2wpkh(&key, Mainnet) returns Err(Error::UncompressedPubkey)
but needs to exercise the P2SH-wrapped path; change the negative assertion to
call Address::p2shwpkh(&key, Mainnet) instead of Address::p2wpkh so that
Address::p2shwpkh is verified to reject uncompressed keys (keep the same
Err(Error::UncompressedPubkey) expectation and the same modified key/compressed
setup).

In `@key-wallet-ffi/FFI_API.md`:
- Around line 2349-2352: The current FFI getters account_get_network,
managed_core_account_get_network, and managed_platform_account_get_network
silently return FFINetwork::Mainnet when given a null FFIAccount pointer; change
each to explicitly detect a null pointer and fail instead of returning Mainnet
by either (a) returning a sentinel/invalid enum such as FFINetwork::Unknown
(preferred) or (b) returning an error/result via the existing FFI
error-reporting mechanism (or setting a global/last-error) so callers can detect
misuse; update the null-check branches in account.rs and managed_account.rs to
perform this explicit failure path and document the new sentinel/error behavior.

In `@key-wallet-ffi/include/key_wallet_ffi.h`:
- Around line 108-110: Add a deprecated compatibility alias for the renamed enum
constant so existing C/Swift consumers keep compiling: in the typedef enum that
now defines MAINNET and TESTNET, add a transitional DASH alias that maps to the
same numeric value as MAINNET (e.g., DASH = MAINNET or DASH = 0) and annotate it
as deprecated (via a comment and/or compiler attribute like
__attribute__((deprecated)) when supported) so the public symbol name remains
available while signaling users to migrate from DASH to MAINNET.

In `@key-wallet-ffi/src/types.rs`:
- Around line 41-45: Replace the wildcard fallback converting upstream Network
to FFINetwork with a fallible, explicit mapping: implement TryFrom<Network> for
FFINetwork (or change the conversion function currently doing the match) so each
known variant (Network::Mainnet, ::Testnet, ::Regtest, ::Devnet) maps explicitly
and any other (future) variant returns an Err (use a descriptive error type or
crate::Error type); update call sites that relied on the infallible conversion
to handle the Result instead of assuming Mainnet.

In `@key-wallet-ffi/src/wallet_manager.rs`:
- Around line 802-805: The code currently sets an error via FFIError::set_error
when manager is null but returns a real network value FFINetwork::Mainnet;
instead add an explicit sentinel variant (e.g., FFINetwork::Unknown or
FFINetwork::Invalid) to the FFINetwork enum, update any serde/FFI mappings, and
change the null-check to return that sentinel rather than Mainnet; keep the
FFIError::set_error call (with FFIErrorCode::InvalidInput) intact so callers can
detect the error distinct from a valid network.

In `@key-wallet/examples/basic_usage.rs`:
- Around line 103-106: The printed network label is stale: after calling
parsed.clone().require_network(DashNetwork::Mainnet) you print "Network: Dash"
using the checked variable; update that println! to reflect the renamed variant
(e.g., print "Network: Mainnet") so it matches the DashNetwork::Mainnet call and
the "Network: Testnet" message used elsewhere.

In `@key-wallet/tests/bip32_tests.rs`:
- Line 13: Current tests only create a master key with
ExtendedPrivKey::new_master(Network::Mainnet, &seed) and miss Testnet coverage;
add parallel assertions that instantiate
ExtendedPrivKey::new_master(Network::Testnet, &seed) (and any derived variables
named `master`/`xprv`/`xpub` in the same test cases) and assert
serialization/deserialization and expected version bytes for Testnet just like
Mainnet checks so both network-specific behaviors are validated; update all
referenced tests (the occurrences around the master-key creation and the cases
at the other mentioned locations) to run the same assertions for
Network::Testnet.

---

Outside diff comments:
In `@key-wallet-ffi/src/derivation_tests.rs`:
- Around line 587-591: derivation_xpriv_to_string may return null, so before
calling CStr::from_ptr on main_str and test_str you must null-check both
pointers (main_str and test_str) and handle the error path similarly to other
tests in this file: if either is null, read/format the error from the existing
error variable and fail the test (or return) rather than calling CStr::from_ptr;
only convert to &CStr and call to_str().unwrap() when the pointer is non-null.
Ensure you reference the same error reporting logic used elsewhere so the test
mirrors the safe pattern.

In `@key-wallet/src/account/account_type.rs`:
- Around line 259-264: In derivation_path ensure you explicitly validate Network
instead of coercing non-Mainnet to coin_type 1; update the coin_type logic in
derivation_path(Network) to match on Network (e.g., Network::Mainnet =>
coin_type = 5, Network::Testnet => coin_type = 1) and return
Err(crate::error::Error::InvalidNetwork) for any other/unsupported variants so
Standard, CoinJoin and provider-key branches don't silently fall back to
testnet; reference derivation_path, Network, coin_type, and
crate::error::Error::InvalidNetwork when making the change.

In `@key-wallet/src/derivation.rs`:
- Around line 137-153: The two unwrap() calls in identity_authentication_key
cause panics when from_hardened_idx fails for values >= 2^31; replace them with
fallible handling by calling from_hardened_idx(...) and using the ? operator (or
map_err to a suitable crate::Error variant) to propagate the error instead of
panicking, e.g. map the child-number error into a new or existing Error variant
(e.g., InvalidChildIndex or similar) so full_path construction returns Err on
bad identity_index or key_index rather than panic.
- Around line 331-350: The match in for_network_and_type currently uses a
catch-all `_ => 5` which silently treats unknown Network variants as mainnet;
change it so the code returns an error for unsupported networks instead of
defaulting to coin_type 5. Update the coin_type match in for_network_and_type to
only handle Network::Mainnet and the explicit test variants and make the default
arm return an Err (e.g., an error indicating Unsupported network) so the
function's Result<DerivationPath> fails for unknown networks; reference the
for_network_and_type method and the Network enum when making this change.

---

Nitpick comments:
In `@dash-spv-ffi/src/config.rs`:
- Around line 116-122: The default_port binding currently hardcodes per-network
P2P ports against cfg.network; replace this literal table with a call into the
shared network constants/helper (e.g. use a function like
network::default_p2p_port(cfg.network) or
shared::network::p2p_port_for(cfg.network)) so the value is sourced from the
canonical network constants instead of inline numbers; update the code that sets
default_port (the let default_port = ... expression) to call that shared helper
and remove the hardcoded match arms.

In `@dash-spv/src/network/tests.rs`:
- Around line 10-17: The test_peer_creation only constructs a Peer with
Network::Mainnet; add a second assertion path that constructs a Peer using
Peer::new(addr, timeout, Network::Testnet) and verifies the same properties (not
connected and address matches) so both network variants are covered; update the
test_peer_creation function to create two peers (one with Network::Mainnet and
one with Network::Testnet) and assert is_connected() is false and address()
equals addr for each.

In `@dash-spv/tests/handshake_test.rs`:
- Around line 16-17: The tests in handshake_test.rs only exercise Peer::connect
with Network::Mainnet; add a Testnet path by parameterizing the tests or
duplicating the calls to cover Network::Testnet as well. Update each call site
using Peer::connect(peer_addr, 10, Network::Mainnet) (and the other occurrences
around the file) to loop over or table-drive both Network::Mainnet and
Network::Testnet so the handshake suite runs for both networks, or add
equivalent assertions for Network::Testnet; ensure you reference
Network::Testnet in the same test functions that currently use Network::Mainnet
(including the sites noted at the other ranges) so both variants are executed by
the test runner.

In `@dash-spv/tests/test_handshake_logic.rs`:
- Around line 8-16: The test currently only constructs HandshakeManager with
Network::Mainnet; add coverage for Network::Testnet by either duplicating the
assertions with a second instance (e.g., let mut handshake =
HandshakeManager::new(Network::Testnet, MempoolStrategy::BloomFilter, None)) or
convert test_handshake_state_transitions into a table-driven loop that iterates
over [Network::Mainnet, Network::Testnet], creating a HandshakeManager for each
and asserting initial state is HandshakeState::Init and that reset() returns it
to Init; reference the HandshakeManager::new constructor, the Network enum
(Testnet), state() and reset() methods when making the change.

In `@dash-spv/tests/transaction_calculation_test.rs`:
- Around line 20-23: The test hardcodes
Address::from_str(...).require_network(Network::Mainnet) which skips exercising
the testnet path; change the failing single-case to a parameterized companion
(or loop) that runs the same assertions for both Network::Mainnet and
Network::Testnet by deriving watched_address for each network using
Address::from_str(...).require_network(network) and reusing the same test logic;
apply the same pattern to the other occurrences that were switched to Mainnet
(the other Address::from_str(...).require_network(...) sites mentioned) so each
regression case runs against both networks.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 15b845c3-30eb-46f6-8a60-62cd918f498f

📥 Commits

Reviewing files that changed from the base of the PR and between 8bca47d and 720a095.

📒 Files selected for processing (76)
  • dash-spv-ffi/FFI_API.md
  • dash-spv-ffi/dash_spv_ffi.h
  • dash-spv-ffi/include/dash_spv_ffi.h
  • dash-spv-ffi/src/bin/ffi_cli.rs
  • dash-spv-ffi/src/config.rs
  • dash-spv-ffi/src/platform_integration.rs
  • dash-spv-ffi/tests/test_config.rs
  • dash-spv-ffi/tests/test_types.rs
  • dash-spv-ffi/tests/test_utils.rs
  • dash-spv-ffi/tests/unit/test_configuration.rs
  • dash-spv-ffi/tests/unit/test_error_handling.rs
  • dash-spv-ffi/tests/unit/test_type_conversions.rs
  • dash-spv/src/chain/chain_work.rs
  • dash-spv/src/client/config.rs
  • dash-spv/src/client/config_test.rs
  • dash-spv/src/client/lifecycle.rs
  • dash-spv/src/main.rs
  • dash-spv/src/mempool_filter.rs
  • dash-spv/src/network/discovery.rs
  • dash-spv/src/network/tests.rs
  • dash-spv/src/test_utils/network.rs
  • dash-spv/src/validation/header.rs
  • dash-spv/tests/handshake_test.rs
  • dash-spv/tests/peer_test.rs
  • dash-spv/tests/test_handshake_logic.rs
  • dash-spv/tests/transaction_calculation_test.rs
  • dash/embedded/src/main.rs
  • dash/examples/handshake.rs
  • dash/src/address.rs
  • dash/src/bip143.rs
  • dash/src/blockdata/constants.rs
  • dash/src/blockdata/transaction/mod.rs
  • dash/src/blockdata/transaction/outpoint.rs
  • dash/src/consensus/params.rs
  • dash/src/crypto/key.rs
  • dash/src/crypto/sighash.rs
  • dash/src/network/constants.rs
  • dash/src/network/message.rs
  • dash/src/sign_message.rs
  • dash/src/sml/llmq_type/network.rs
  • dash/src/sml/masternode_list/apply_diff.rs
  • dash/src/sml/masternode_list/from_diff.rs
  • dash/src/sml/masternode_list_engine/mod.rs
  • dash/src/taproot.rs
  • fuzz/fuzz_targets/dash/deserialize_script.rs
  • key-wallet-ffi/FFI_API.md
  • key-wallet-ffi/include/key_wallet_ffi.h
  • key-wallet-ffi/src/account.rs
  • key-wallet-ffi/src/account_tests.rs
  • key-wallet-ffi/src/derivation_tests.rs
  • key-wallet-ffi/src/lib_tests.rs
  • key-wallet-ffi/src/managed_account.rs
  • key-wallet-ffi/src/types.rs
  • key-wallet-ffi/src/wallet_manager.rs
  • key-wallet-ffi/tests/debug_addr.rs
  • key-wallet-ffi/tests/integration_test.rs
  • key-wallet/CLAUDE.md
  • key-wallet/README.md
  • key-wallet/examples/basic_usage.rs
  • key-wallet/src/account/account_type.rs
  • key-wallet/src/bip32.rs
  • key-wallet/src/bip38.rs
  • key-wallet/src/bip38_tests.rs
  • key-wallet/src/derivation.rs
  • key-wallet/src/derivation_slip10.rs
  • key-wallet/src/managed_account/address_pool.rs
  • key-wallet/src/psbt/mod.rs
  • key-wallet/src/tests/account_tests.rs
  • key-wallet/src/tests/backup_restore_tests.rs
  • key-wallet/src/tests/edge_case_tests.rs
  • key-wallet/src/tests/integration_tests.rs
  • key-wallet/src/wallet/mod.rs
  • key-wallet/tests/address_tests.rs
  • key-wallet/tests/bip32_tests.rs
  • key-wallet/tests/derivation_tests.rs
  • key-wallet/tests/mnemonic_tests.rs

Comment on lines +103 to 106
if let Ok(checked) = parsed.clone().require_network(DashNetwork::Mainnet) {
println!(" Parsed address: {}", checked);
println!(" Type: {:?}", checked.address_type());
println!(" Network: Dash");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Update output string to match renamed variant.

Line 103 correctly uses DashNetwork::Mainnet, but line 106 still prints "Network: Dash". For consistency with the rename and with line 110 (which prints "Network: Testnet"), consider updating the output.

Proposed fix
             if let Ok(checked) = parsed.clone().require_network(DashNetwork::Mainnet) {
                 println!("   Parsed address: {}", checked);
                 println!("   Type: {:?}", checked.address_type());
-                println!("   Network: Dash");
+                println!("   Network: Mainnet");
             } else if let Ok(checked) = parsed.require_network(DashNetwork::Testnet) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if let Ok(checked) = parsed.clone().require_network(DashNetwork::Mainnet) {
println!(" Parsed address: {}", checked);
println!(" Type: {:?}", checked.address_type());
println!(" Network: Dash");
if let Ok(checked) = parsed.clone().require_network(DashNetwork::Mainnet) {
println!(" Parsed address: {}", checked);
println!(" Type: {:?}", checked.address_type());
println!(" Network: Mainnet");
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@key-wallet/examples/basic_usage.rs` around lines 103 - 106, The printed
network label is stale: after calling
parsed.clone().require_network(DashNetwork::Mainnet) you print "Network: Dash"
using the checked variable; update that println! to reflect the renamed variant
(e.g., print "Network: Mainnet") so it matches the DashNetwork::Mainnet call and
the "Network: Testnet" message used elsewhere.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
key-wallet/src/bip38.rs (1)

86-95: ⚠️ Potential issue | 🔴 Critical

Don't silently force deserialized keys onto Mainnet.

Line 89 makes every parsed BIP38 key verify against mainnet addresses. That breaks a real round-trip: a key encrypted with Network::Testnet can be serialized with to_base58(), but from_base58() reconstructs it as mainnet and decrypt() then fails the address-hash check with a false "invalid password" error. Please make the caller provide the network context here, or defer address verification until the network is known.

💡 Minimal fix
-    pub fn from_base58(s: &str) -> Result<Self> {
+    pub fn from_base58(s: &str, network: Network) -> Result<Self> {
         let data = bs58::decode(s)
             .with_check(None)
             .into_vec()
             .map_err(|_| Error::InvalidParameter("Invalid base58 encoding".into()))?;
@@
-        // Try to determine network from address hash
-        // In BIP38, bytes 3-6 are the address hash
-        // We'll default to mainnet for now
-        let network = Network::Mainnet;
-
         Ok(Self {
             data,
             mode,
             compressed,
             network,
         })
     }

A follow-up regression test for Network::Testnet through to_base58()from_base58()decrypt() would lock this down.

As per coding guidelines, "Always validate network consistency when deriving or validating addresses; never mix mainnet and testnet operations".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@key-wallet/src/bip38.rs` around lines 86 - 95, The code currently forces
Network::Mainnet during BIP38 deserialization which breaks round-trips and
causes false "invalid password" errors; update the BIP38 deserialization path
(the function performing from_base58() / the constructor returning Self with
fields data, mode, compressed, network) to either accept a Network parameter
from the caller or leave network unset/unknown and defer the address-hash
verification until decrypt() (or until the caller supplies the network) so you
do not assume mainnet; ensure decrypt() (or the verification routine) checks
consistency against the provided network and update signatures of
from_base58()/to_base58()/decrypt() accordingly so testnet keys round-trip
correctly.
key-wallet-ffi/tests/debug_addr.rs (1)

9-31: ⚠️ Potential issue | 🟡 Minor

This test never verifies the Mainnet rename.

Both the parse branch and each require_network branch only log, so this still passes if Mainnet mapping regresses or parsing fails outright. Please turn this into an asserting test with explicit expected outcomes instead of a debug print loop.

As per coding guidelines **/*.rs: Write unit tests for new functionality in Rust code.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@key-wallet-ffi/tests/debug_addr.rs` around lines 9 - 31, Replace the
debug-only prints in the test with real assertions: call
key_wallet::Address::from_str(addr_str) and assert it returns Ok(address); then
for each network in the test vector use address.clone().require_network(network)
and assert the expected outcome (e.g., assert_ok for dashcore::Network::Mainnet
to verify the Mainnet rename mapping and assert_err for the other networks if
they should fail). Use explicit assert!(matches!(...)) or assert_eq! on the
returned checked string where appropriate so the test will fail if parsing or
the Mainnet mapping regresses; reference Address::from_str and .require_network
to locate the code to change.
dash-spv/tests/test_handshake_logic.rs (1)

8-16: ⚠️ Potential issue | 🟡 Minor

Add a Testnet coverage path for this network-specific test.

This file now only exercises Network::Mainnet. A regression in HandshakeManager::new or reset() for Testnet would slip through even though this is the network-selection surface touched by the rename.

🧪 Proposed change
-#[test]
-fn test_handshake_state_transitions() {
-    let mut handshake = HandshakeManager::new(Network::Mainnet, MempoolStrategy::BloomFilter, None);
+fn assert_handshake_state_transitions(network: Network) {
+    let mut handshake = HandshakeManager::new(network, MempoolStrategy::BloomFilter, None);

     // Initial state should be Init
     assert_eq!(*handshake.state(), HandshakeState::Init);

     // After reset, should be back to Init
     handshake.reset();
     assert_eq!(*handshake.state(), HandshakeState::Init);
 }
+
+#[test]
+fn test_handshake_state_transitions_mainnet() {
+    assert_handshake_state_transitions(Network::Mainnet);
+}
+
+#[test]
+fn test_handshake_state_transitions_testnet() {
+    assert_handshake_state_transitions(Network::Testnet);
+}
As per coding guidelines, `**/*test*.rs`: Test both mainnet and testnet configurations.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@dash-spv/tests/test_handshake_logic.rs` around lines 8 - 16, The test only
covers Network::Mainnet so add a symmetric path for Network::Testnet: duplicate
the assertions but construct HandshakeManager::new with Network::Testnet and the
same MempoolStrategy::BloomFilter (or iterate over both networks) and assert
that *handshake.state() == HandshakeState::Init before and after calling
handshake.reset(); reference HandshakeManager::new, HandshakeManager::reset,
HandshakeManager::state, HandshakeState and Network::Testnet to locate where to
add the additional test case in test_handshake_logic.rs.
♻️ Duplicate comments (4)
key-wallet-ffi/src/account.rs (1)

233-239: ⚠️ Potential issue | 🟠 Major

Null account handles shouldn’t look like Mainnet.

Returning FFINetwork::Mainnet for a null FFI handle converts invalid input into a valid-looking network value, which hides caller bugs and can misroute mainnet/testnet logic. Please return an explicit sentinel/error path instead of defaulting to Mainnet.

As per coding guidelines **/*-ffi/**/*.rs: Handle memory safety carefully at FFI boundaries.

Also applies to: 344-351, 461-468

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@key-wallet-ffi/src/account.rs` around lines 233 - 239, The function
account_get_network currently returns FFINetwork::Mainnet for null FFIAccount
which masks errors; change the null-path to return an explicit sentinel (e.g.,
add and use FFINetwork::Unknown or FFINetwork::Invalid) instead of Mainnet, and
propagate the same fix to the other FFI functions noted (around the other
occurrences) so all null-handle checks return the sentinel; also update any FFI
consumers/signature docs to recognize the new sentinel.
key-wallet-ffi/src/types.rs (1)

38-46: ⚠️ Potential issue | 🟠 Major

Don’t coerce unknown Network variants to Mainnet.

That wildcard arm turns any unsupported upstream variant into a valid-looking mainnet value for FFI callers. This should be explicit/fallible instead of silently remapping.

#!/bin/bash
set -euo pipefail

echo "Inspect upstream Network definition:"
rg -nC3 --glob '*.rs' '#\[non_exhaustive\]|pub enum Network'

echo
echo "Inspect the FFI conversion in key-wallet-ffi/src/types.rs:"
rg -nC4 --glob 'key-wallet-ffi/src/types.rs' 'impl From<Network> for FFINetwork|_ => FFINetwork::Mainnet'

Expected result: if Network is still non-exhaustive and this wildcard fallback remains, the conversion can silently misclassify future variants as Mainnet.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@key-wallet-ffi/src/types.rs` around lines 38 - 46, The current impl
From<Network> for FFINetwork silently maps any unknown Network variant to
FFINetwork::Mainnet via the wildcard arm; change this to an explicit/fallible
conversion by removing the `_ => FFINetwork::Mainnet` arm and implementing
TryFrom<Network> for FFINetwork (or otherwise returning Result<FFINetwork, _>)
from the From::from logic so unknown variants produce an Err; update callers
that relied on the infallible conversion to handle the Result and add a clear
Conversion/FFI error type or message to indicate unsupported Network variants
(reference the impl From<Network> for FFINetwork, the match over `net`, and the
From::from/TryFrom::try_from implementations).
key-wallet/examples/basic_usage.rs (1)

103-106: ⚠️ Potential issue | 🟡 Minor

Update the printed network label to Mainnet.

Line 106 still prints "Network: Dash" even though this branch is gated by require_network(DashNetwork::Mainnet), so the example output is now internally inconsistent.

🩹 Proposed fix
             if let Ok(checked) = parsed.clone().require_network(DashNetwork::Mainnet) {
                 println!("   Parsed address: {}", checked);
                 println!("   Type: {:?}", checked.address_type());
-                println!("   Network: Dash");
+                println!("   Network: Mainnet");
             } else if let Ok(checked) = parsed.require_network(DashNetwork::Testnet) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@key-wallet/examples/basic_usage.rs` around lines 103 - 106, The printed
network label is wrong in the require_network(DashNetwork::Mainnet) branch:
update the println that currently emits "Network: Dash" to print "Network:
Mainnet" so the output for the checked variable (from
parsed.clone().require_network and bound to checked) correctly reflects the
Mainnet branch; locate the two println! calls that print the parsed address and
type and modify the third println! for the network label accordingly.
dash-spv/src/network/discovery.rs (1)

34-36: ⚠️ Potential issue | 🟠 Major

Stop hardcoding the P2P port in discovery.

Lines 35-36 still inline 9999/19999. That duplicates network parameters in production discovery code, so a future port change can desynchronize DNS seed selection from the actual connection port.

As per coding guidelines, **/*.rs: Never hardcode network parameters, addresses, or keys in Rust code.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@dash-spv/src/network/discovery.rs` around lines 34 - 36, The code currently
hardcodes P2P ports (9999/19999) in the match that picks (MAINNET_DNS_SEEDS,
9999) / (TESTNET_DNS_SEEDS, 19999); replace those literal ports by reading the
network's canonical port from the network parameters instead (e.g., call a
function or field such as Network::default_port(), network.p2p_port(), or the
project’s NetworkParams::p2p_port) so the tuple becomes (MAINNET_DNS_SEEDS,
network_p2p_port) / (TESTNET_DNS_SEEDS, network_p2p_port); update the match
around Network::Mainnet / Network::Testnet and use the existing
MAINNET_DNS_SEEDS and TESTNET_DNS_SEEDS symbols to locate the change.
🧹 Nitpick comments (1)
dash-spv-ffi/tests/unit/test_configuration.rs (1)

10-22: Test function name is misleading.

The function test_config_with_invalid_network actually tests valid networks (Mainnet, Testnet, Regtest, Devnet) rather than invalid ones. Consider renaming to test_config_with_valid_networks or similar for clarity.

The network array update from Dash to Mainnet is correct and aligns with the PR objective.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@dash-spv-ffi/tests/unit/test_configuration.rs` around lines 10 - 22, The test
function name test_config_with_invalid_network is misleading because it actually
iterates valid networks; rename the function to something like
test_config_with_valid_networks and update any references or test attributes
accordingly so the name reflects behavior; keep the body using
dash_spv_ffi_config_new, dash_spv_ffi_config_get_network and
dash_spv_ffi_config_destroy unchanged and ensure the new function name is used
anywhere the test is referenced.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@dash-spv/tests/test_handshake_logic.rs`:
- Around line 8-16: The test only covers Network::Mainnet so add a symmetric
path for Network::Testnet: duplicate the assertions but construct
HandshakeManager::new with Network::Testnet and the same
MempoolStrategy::BloomFilter (or iterate over both networks) and assert that
*handshake.state() == HandshakeState::Init before and after calling
handshake.reset(); reference HandshakeManager::new, HandshakeManager::reset,
HandshakeManager::state, HandshakeState and Network::Testnet to locate where to
add the additional test case in test_handshake_logic.rs.

In `@key-wallet-ffi/tests/debug_addr.rs`:
- Around line 9-31: Replace the debug-only prints in the test with real
assertions: call key_wallet::Address::from_str(addr_str) and assert it returns
Ok(address); then for each network in the test vector use
address.clone().require_network(network) and assert the expected outcome (e.g.,
assert_ok for dashcore::Network::Mainnet to verify the Mainnet rename mapping
and assert_err for the other networks if they should fail). Use explicit
assert!(matches!(...)) or assert_eq! on the returned checked string where
appropriate so the test will fail if parsing or the Mainnet mapping regresses;
reference Address::from_str and .require_network to locate the code to change.

In `@key-wallet/src/bip38.rs`:
- Around line 86-95: The code currently forces Network::Mainnet during BIP38
deserialization which breaks round-trips and causes false "invalid password"
errors; update the BIP38 deserialization path (the function performing
from_base58() / the constructor returning Self with fields data, mode,
compressed, network) to either accept a Network parameter from the caller or
leave network unset/unknown and defer the address-hash verification until
decrypt() (or until the caller supplies the network) so you do not assume
mainnet; ensure decrypt() (or the verification routine) checks consistency
against the provided network and update signatures of
from_base58()/to_base58()/decrypt() accordingly so testnet keys round-trip
correctly.

---

Duplicate comments:
In `@dash-spv/src/network/discovery.rs`:
- Around line 34-36: The code currently hardcodes P2P ports (9999/19999) in the
match that picks (MAINNET_DNS_SEEDS, 9999) / (TESTNET_DNS_SEEDS, 19999); replace
those literal ports by reading the network's canonical port from the network
parameters instead (e.g., call a function or field such as
Network::default_port(), network.p2p_port(), or the project’s
NetworkParams::p2p_port) so the tuple becomes (MAINNET_DNS_SEEDS,
network_p2p_port) / (TESTNET_DNS_SEEDS, network_p2p_port); update the match
around Network::Mainnet / Network::Testnet and use the existing
MAINNET_DNS_SEEDS and TESTNET_DNS_SEEDS symbols to locate the change.

In `@key-wallet-ffi/src/account.rs`:
- Around line 233-239: The function account_get_network currently returns
FFINetwork::Mainnet for null FFIAccount which masks errors; change the null-path
to return an explicit sentinel (e.g., add and use FFINetwork::Unknown or
FFINetwork::Invalid) instead of Mainnet, and propagate the same fix to the other
FFI functions noted (around the other occurrences) so all null-handle checks
return the sentinel; also update any FFI consumers/signature docs to recognize
the new sentinel.

In `@key-wallet-ffi/src/types.rs`:
- Around line 38-46: The current impl From<Network> for FFINetwork silently maps
any unknown Network variant to FFINetwork::Mainnet via the wildcard arm; change
this to an explicit/fallible conversion by removing the `_ =>
FFINetwork::Mainnet` arm and implementing TryFrom<Network> for FFINetwork (or
otherwise returning Result<FFINetwork, _>) from the From::from logic so unknown
variants produce an Err; update callers that relied on the infallible conversion
to handle the Result and add a clear Conversion/FFI error type or message to
indicate unsupported Network variants (reference the impl From<Network> for
FFINetwork, the match over `net`, and the From::from/TryFrom::try_from
implementations).

In `@key-wallet/examples/basic_usage.rs`:
- Around line 103-106: The printed network label is wrong in the
require_network(DashNetwork::Mainnet) branch: update the println that currently
emits "Network: Dash" to print "Network: Mainnet" so the output for the checked
variable (from parsed.clone().require_network and bound to checked) correctly
reflects the Mainnet branch; locate the two println! calls that print the parsed
address and type and modify the third println! for the network label
accordingly.

---

Nitpick comments:
In `@dash-spv-ffi/tests/unit/test_configuration.rs`:
- Around line 10-22: The test function name test_config_with_invalid_network is
misleading because it actually iterates valid networks; rename the function to
something like test_config_with_valid_networks and update any references or test
attributes accordingly so the name reflects behavior; keep the body using
dash_spv_ffi_config_new, dash_spv_ffi_config_get_network and
dash_spv_ffi_config_destroy unchanged and ensure the new function name is used
anywhere the test is referenced.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 102cc016-ae4d-4dc9-a009-611847775305

📥 Commits

Reviewing files that changed from the base of the PR and between 720a095 and faa0edd.

📒 Files selected for processing (77)
  • dash-spv-ffi/FFI_API.md
  • dash-spv-ffi/dash_spv_ffi.h
  • dash-spv-ffi/include/dash_spv_ffi.h
  • dash-spv-ffi/scripts/generate_ffi_docs.py
  • dash-spv-ffi/src/bin/ffi_cli.rs
  • dash-spv-ffi/src/config.rs
  • dash-spv-ffi/src/platform_integration.rs
  • dash-spv-ffi/tests/test_config.rs
  • dash-spv-ffi/tests/test_types.rs
  • dash-spv-ffi/tests/test_utils.rs
  • dash-spv-ffi/tests/unit/test_configuration.rs
  • dash-spv-ffi/tests/unit/test_error_handling.rs
  • dash-spv-ffi/tests/unit/test_type_conversions.rs
  • dash-spv/src/chain/chain_work.rs
  • dash-spv/src/client/config.rs
  • dash-spv/src/client/config_test.rs
  • dash-spv/src/client/lifecycle.rs
  • dash-spv/src/main.rs
  • dash-spv/src/mempool_filter.rs
  • dash-spv/src/network/discovery.rs
  • dash-spv/src/network/tests.rs
  • dash-spv/src/test_utils/network.rs
  • dash-spv/src/validation/header.rs
  • dash-spv/tests/handshake_test.rs
  • dash-spv/tests/peer_test.rs
  • dash-spv/tests/test_handshake_logic.rs
  • dash-spv/tests/transaction_calculation_test.rs
  • dash/embedded/src/main.rs
  • dash/examples/handshake.rs
  • dash/src/address.rs
  • dash/src/bip143.rs
  • dash/src/blockdata/constants.rs
  • dash/src/blockdata/transaction/mod.rs
  • dash/src/blockdata/transaction/outpoint.rs
  • dash/src/consensus/params.rs
  • dash/src/crypto/key.rs
  • dash/src/crypto/sighash.rs
  • dash/src/network/constants.rs
  • dash/src/network/message.rs
  • dash/src/sign_message.rs
  • dash/src/sml/llmq_type/network.rs
  • dash/src/sml/masternode_list/apply_diff.rs
  • dash/src/sml/masternode_list/from_diff.rs
  • dash/src/sml/masternode_list_engine/mod.rs
  • dash/src/taproot.rs
  • fuzz/fuzz_targets/dash/deserialize_script.rs
  • key-wallet-ffi/FFI_API.md
  • key-wallet-ffi/include/key_wallet_ffi.h
  • key-wallet-ffi/src/account.rs
  • key-wallet-ffi/src/account_tests.rs
  • key-wallet-ffi/src/derivation_tests.rs
  • key-wallet-ffi/src/lib_tests.rs
  • key-wallet-ffi/src/managed_account.rs
  • key-wallet-ffi/src/types.rs
  • key-wallet-ffi/src/wallet_manager.rs
  • key-wallet-ffi/tests/debug_addr.rs
  • key-wallet-ffi/tests/integration_test.rs
  • key-wallet/CLAUDE.md
  • key-wallet/README.md
  • key-wallet/examples/basic_usage.rs
  • key-wallet/src/account/account_type.rs
  • key-wallet/src/bip32.rs
  • key-wallet/src/bip38.rs
  • key-wallet/src/bip38_tests.rs
  • key-wallet/src/derivation.rs
  • key-wallet/src/derivation_slip10.rs
  • key-wallet/src/managed_account/address_pool.rs
  • key-wallet/src/psbt/mod.rs
  • key-wallet/src/tests/account_tests.rs
  • key-wallet/src/tests/backup_restore_tests.rs
  • key-wallet/src/tests/edge_case_tests.rs
  • key-wallet/src/tests/integration_tests.rs
  • key-wallet/src/wallet/mod.rs
  • key-wallet/tests/address_tests.rs
  • key-wallet/tests/bip32_tests.rs
  • key-wallet/tests/derivation_tests.rs
  • key-wallet/tests/mnemonic_tests.rs
🚧 Files skipped from review as they are similar to previous changes (45)
  • key-wallet/src/tests/backup_restore_tests.rs
  • key-wallet/src/tests/edge_case_tests.rs
  • key-wallet-ffi/src/wallet_manager.rs
  • dash-spv/src/mempool_filter.rs
  • dash/src/taproot.rs
  • dash-spv-ffi/src/platform_integration.rs
  • dash/src/blockdata/constants.rs
  • key-wallet/src/bip38_tests.rs
  • key-wallet-ffi/tests/integration_test.rs
  • dash-spv-ffi/tests/unit/test_type_conversions.rs
  • dash/src/sign_message.rs
  • dash/src/sml/masternode_list/from_diff.rs
  • key-wallet/src/psbt/mod.rs
  • key-wallet-ffi/include/key_wallet_ffi.h
  • key-wallet/tests/mnemonic_tests.rs
  • dash-spv-ffi/tests/test_utils.rs
  • dash-spv/src/client/lifecycle.rs
  • key-wallet/tests/bip32_tests.rs
  • key-wallet/src/managed_account/address_pool.rs
  • dash-spv/src/validation/header.rs
  • dash/src/crypto/sighash.rs
  • dash-spv-ffi/src/config.rs
  • key-wallet-ffi/src/managed_account.rs
  • dash/src/blockdata/transaction/outpoint.rs
  • dash/examples/handshake.rs
  • key-wallet/README.md
  • dash/src/blockdata/transaction/mod.rs
  • key-wallet/src/tests/account_tests.rs
  • key-wallet-ffi/src/lib_tests.rs
  • dash-spv/src/network/tests.rs
  • dash-spv/tests/peer_test.rs
  • dash/embedded/src/main.rs
  • dash/src/network/message.rs
  • dash-spv-ffi/tests/test_config.rs
  • dash-spv/src/test_utils/network.rs
  • dash/src/sml/llmq_type/network.rs
  • key-wallet/src/derivation_slip10.rs
  • dash-spv-ffi/include/dash_spv_ffi.h
  • dash-spv/src/client/config_test.rs
  • dash-spv/tests/handshake_test.rs
  • key-wallet/tests/derivation_tests.rs
  • dash/src/sml/masternode_list_engine/mod.rs
  • key-wallet/CLAUDE.md
  • dash-spv-ffi/tests/test_types.rs
  • dash-spv-ffi/dash_spv_ffi.h

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant