You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit ae29a45
Browse filesBrowse the repository at this point in the historyBrowse files
feat(qt): DashPay opt-in, privacy gating and Platform network checks
Add the DashPay tab (behind the Show DashPay Tab option, default off) with the per-wallet opt-in it needs before anything contacts Platform. The opt-in dialog says the wallet connects to Dash Platform through evonodes and what the evonode answering each request can see (your IP address, or your proxy's; your identity and what it looks up; the usernames you search for), that connections are encrypted and use the same network settings and proxy as the rest of Dash Core, and that usernames, profiles and contact requests are public. It writes only the platform/enabled record and the record layout version. The chain id the records belong to is never taken from configuration: the first read the client verified stamps platform/chain-id with the chain id it was verified for.
PlatformPage::maybeCreateService constructs the PlatformService only when the wallet opted in, is a descriptor wallet holding its own keys, the node's network settings leave DashPay a network to use, network activity is on and the node has a ChainLock; otherwise the page shows the reason. DashPay connects to evonodes as Core connects to its peers (PlatformRoute): with IPv4 or IPv6 reachable, through -proxy or directly, to evonodes on those networks, and to onion ones only when the onion proxy is that same proxy; with only onion reachable (-onlynet=onion), through the onion proxy to onion evonodes; never to I2P or CJDNS ones. The reachable networks come from interfaces::Node::isReachable and the proxies from getProxy, so -onion, -noonion and the Tor controller's onion proxy count, not -onlynet alone. The route is chosen once when the service is created, its proxy configures the client, and only evonodes on it are pushed; when the masternode list has evonodes but none on the route, nothing is pushed and the page says no evonode can be reached over the networks the settings allow. The service pushes an empty endpoint set while network activity is off, feeds evonode endpoints, Platform quorum keys and the best ChainLock height into the client on a timer and on every NotifyChainLock, and mints the SigningOperation every write signs under, which needs a wallet unlock that is released with the operation. Every client status passes through the service: an UnsupportedProtocolVersion freezes writes; a CHAIN_ID_MISMATCH on any response enters the mismatch state, which blocks writes until a verified read clears it; and records stamped for another chain id enter the network-changed state, which offers to discard the local Platform state and re-scan rather than leaving the wallet registered on a chain that no longer exists.
-platformchainid is a GUI-only argument applied on testnet and devnets and refused at startup on mainnet; the chain id itself comes from CChainParams::PlatformChainId(). The mismatch text names -platformchainid only when it is set. WalletModel::UnlockContext becomes movable so an operation can own it. After this commit the tab shows only the opt-in state; usernames, contacts and payments follow.
Tests (test_dash-qt PlatformTests over FakePlatformClient): no service and no client with the opt-in off; opting in records no chain id; with no network DashPay can use the service is refused with a reason, while a proxy is no gate; the route for Core's defaults, -proxy, -proxy with -onion or -noonion, a Unix socket proxy, -onlynet=ipv4 and -onlynet=onion with and without an onion proxy, never reaching I2P, and read from the node's reachable networks (routeSelection); evonodes off the route not pushed and reported until one on it is (endpointsOffTheRouteAreNotPushed); the opt-in text names evonodes and the proxy and not other people or a proxy left unused (optInDisclosureCopy); the mainnet chain id is never overridden; records for another chain enter the network-changed state where nothing signs until they are discarded, and discarding leaves the chain id to the next verified read; an inactive network pushes an empty endpoint set; opting out wipes every record; every failure kind has a user-visible description and OK/AlreadyExists have none.
The welcome and network-changed panels are a centred column between stretches rather than an aligned widget, so wrapped text gets the height its width needs, and a card whose text changes is measured again. When -platformchainid is set, the network-changed page says the setting may be what is wrong. The service pushes endpoints again as soon as network activity is back and reports when endpoints return (endpointsAvailable) and when network activity changes. A context change that comes while the endpoints are being collected (network activity turned off or on again quickly) has them collected again when that collection lands, not at the next timer tick, and the collection made before the change is dropped rather than pushed, so a set gathered while network activity was on never reaches the client after it was turned off. A message line can show a message that clears itself after a few seconds, and Show details text is built from the failed step's operation, status and time. Headings use the Overview page's section size. Test: network activity off empties the client's endpoints, turning it on pushes them again at once, a quick off and on collects them again, and a quick on and off pushes only the empty set (networkResumePushesEndpointsAgain).
The page is built from shared DashPay building blocks (qt/platform/platformui): the masternode dialogs' secondary-button style, busy bar and hints, and a message line with a Show details / Copy details disclosure. A failed Platform call is described in plain sentences mapped from its status kind and rs-dpp consensus code; the raw result is only in the details. A page that cannot start names what resolves it (Turn network on) or, for network settings, says what DashPay needs. Test: status descriptions are sentences without codes or internal messages, with the result in the details, and the mismatch text mentions -platformchainid only when it is set.
DashPay is turned on and off in Options, Wallet, in a DashPay group for the wallet the main window shows (DashPayOptionsWidget). Opting in is a per-wallet record, not a global setting, so the group names the wallet, says each wallet has its own setting, and its Enable DashPay… or Disable DashPay… acts at once through the opt-in or a confirmation whose default is Cancel and whose destructive button is secondary, like Reset Options, never through the dialog's OK or Cancel. The DashPay tab has no Disable button: where DashPay is on but not working, the welcome and network-changed pages offer DashPay settings…, which opens that group. The Show DashPay Tab tooltip says hiding the tab does not turn DashPay off. Test: the group turns DashPay on through the opt-in and off through the confirmation, Cancel changes nothing, and the tab offers no Disable button (dashPayOptionsSection).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
argsman.AddArg("-uiplatform", strprintf("Select platform to customize UI for (one of windows, macosx, other; default: %s)", GUIUtil::defaultUIPlatform()), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::GUI);
499
499
argsman.AddArg("-debug-ui", "Updates the UI's stylesheets in realtime with changes made to the css files in -custom-css-dir and forces some widgets to show up which are usually only visible under certain circumstances. (default: 0)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::GUI);
500
500
argsman.AddArg("-windowtitle=<name>", _("Sets a window title which is appended to \"Dash Core - \"").translated, ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
501
+
#ifdef ENABLE_PLATFORM_GUI
502
+
argsman.AddArg("-platformchainid=<id>", "Tenderdash chain id DashPay verifies Platform responses against on testnet and devnets (GUI only; the chain id of mainnet cannot be overridden)", ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
503
+
#endif
501
504
}
502
505
503
506
intGuiMain(int argc, char* argv[])
@@ -638,6 +641,14 @@ int GuiMain(int argc, char* argv[])
<string>Show additional tab for DashPay usernames, profiles and contacts on Dash Platform. Hiding the tab doesn't turn DashPay off; use Wallet → DashPay for that.</string>
0 commit comments