What changed, and why it matters
This commit fixes how the app displays the status of Firo masternodes. Previously, a masternode was shown as either 'ACTIVE' or 'REVOKED' based only on whether it had been revoked. Now it also recognizes a 'BANNED' state (when the node has been banned for misbehavior). This is a UI/accuracy improvement, not a security vulnerability fix.
No security action required. Treat as a routine UI correctness update. If reviewing, verify that the poseBanHeight and revocationReason fields are populated correctly from the Firo RPC/daemon response.
Security signals we found
No security-relevant signals present in diff or commit metadata
Change is limited to UI status display and label coloring
Evidence from the diff
The patch introduces a MasternodeStatus enum with active, banned, and revoked states and a computed status getter on MasternodeInfo. The UI now uses this status to choose label text and badge color (green/orange/red). The previous logic treated revocationReason == 0 as active and everything else as revoked, which failed to distinguish banned-but-not-revoked masternodes. The change is purely presentational and does not alter wallet logic, RPC handling, or cryptographic operations.
Changed components
lib/pages/masternodes/sub_widgets/masternodes_list.dartlib/wallets/wallet/impl/firo_wallet.dartInspect captured patch +30 / −13
### lib/pages/masternodes/sub_widgets/masternodes_list.dart
@@ -68,16 +68,15 @@ class _MasternodeCard extends StatelessWidget {
),
);
} else {
- await Navigator.of(
- context,
- ).pushNamed(MasternodeDetailsView.routeName, arguments: node);
+ await Navigator.of(context)
+ .pushNamed(MasternodeDetailsView.routeName, arguments: node);
}
}
@override
Widget build(BuildContext context) {
final stack = Theme.of(context).extension<StackColors>()!;
- final isActive = node.revocationReason == 0;
+ final status = node.status;
return RoundedWhiteContainer(
padding: const EdgeInsets.all(16),
@@ -97,9 +96,8 @@ class _MasternodeCard extends StatelessWidget {
const SizedBox(height: 2),
Text(
"Last paid height: ${node.lastPaidHeight}",
- style: STextStyles.baseXS(
- context,
- ).copyWith(color: stack.textSubtitle1),
+ style: STextStyles.baseXS(context)
+ .copyWith(color: stack.textSubtitle1),
),
],
),
@@ -108,14 +106,17 @@ class _MasternodeCard extends StatelessWidget {
Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
- color: isActive ? stack.accentColorGreen : stack.accentColorRed,
+ color: switch (status) {
+ MasternodeStatus.active => stack.accentColorGreen,
+ MasternodeStatus.banned => stack.accentColorOrange,
+ MasternodeStatus.revoked => stack.accentColorRed,
+ },
borderRadius: BorderRadius.circular(8),
),
child: Text(
- isActive ? "ACTIVE" : "REVOKED",
- style: STextStyles.w600_12(
- context,
- ).copyWith(color: stack.textWhite),
+ status.label,
+ style: STextStyles.w600_12(context)
+ .copyWith(color: stack.textWhite),
),
),
],
### lib/wallets/wallet/impl/firo_wallet.dart
@@ -32,6 +32,16 @@ import '../wallet_mixin_interfaces/extended_keys_interface.dart';
import '../wallet_mixin_interfaces/spark_interface.dart';
import 'firo_transaction_type.dart';
+enum MasternodeStatus {
+ active("ACTIVE"),
+ banned("BANNED"),
+ revoked("REVOKED");
+
+ const MasternodeStatus(this.label);
+
+ final String label;
+}
+
class MasternodeInfo {
final String proTxHash;
final String collateralHash;
@@ -71,11 +81,17 @@ class MasternodeInfo {
required this.pubKeyOperator,
});
+ MasternodeStatus get status {
+ if (revocationReason != 0) return MasternodeStatus.revoked;
+ if (poseBanHeight != -1) return MasternodeStatus.banned;
+ return MasternodeStatus.active;
+ }
+
Map<String, String> pretty() {
return {
"ProTx Hash": proTxHash,
"IP:Port": "$serviceAddr:$servicePort",
- "Status": revocationReason == 0 ? "Active" : "Revoked",
+ "Status": status.label,
"Registered Height": registeredHeight.toString(),
"Last Paid Height": lastPaidHeight.toString(),
"Payout Address": payoutAddress,Why this scored 19/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.