Merge pull request #1453 from levoncrypto/masternode-payout-ui
What changed, and why it matters
This change updates the Firo wallet's masternode owner address selection so that the chosen owner address is different from both the collateral address and the payout address. Previously, the code only ensured the owner address differed from the collateral address. The change appears to prevent a configuration where the owner, collateral, and payout addresses overlap, which could cause issues with masternode registration or rewards. There is no direct evidence in the commit that this fixes an active security vulnerability, but address reuse or overlap in masternode operations can have privacy and operational risks.
Review whether the payoutAddress is reliably populated before this code runs; if it can be null or empty, consider whether the distinctness check should handle those cases explicitly. Otherwise, no immediate action is required beyond normal testing of masternode creation flows.
Security signals we found
Defensive address-distinctness check added for masternode owner address
Prevents owner address from matching payout address, not just collateral address
Error message updated to reflect new dual-distinctness requirement
Evidence from the diff
In lib/wallets/wallet/impl/firo_wallet.dart, the masternode owner address derivation loop now checks that the selected address is distinct from both collateralAddress and payoutAddress. A new helper isUsableOwner() encapsulates the condition. The loop and final validation now use this helper, and the error message reflects the new requirement. The change is small and defensive, reducing the chance that owner, collateral, and payout addresses coincide during masternode setup.
Changed components
lib/wallets/wallet/impl/firo_wallet.dartFiro masternode owner address derivationInspect captured patch +9 / −8
### lib/wallets/wallet/impl/firo_wallet.dart
@@ -1020,20 +1020,21 @@ class FiroWallet<T extends ElectrumXCurrencyInterface> extends Bip39HDWallet<T>
);
}
+ bool isUsableOwner(Address? address) =>
+ address != null &&
+ address.value != collateralAddress &&
+ address.value != payoutAddress;
+
Address? ownerAddress = await getCurrentReceivingAddress();
const maxOwnerAttempts = 32;
- for (
- var i = 0;
- i < maxOwnerAttempts &&
- (ownerAddress == null || ownerAddress.value == collateralAddress);
- i++
- ) {
+ for (var i = 0; i < maxOwnerAttempts && !isUsableOwner(ownerAddress); i++) {
await generateNewReceivingAddress();
ownerAddress = await getCurrentReceivingAddress();
}
- if (ownerAddress == null || ownerAddress.value == collateralAddress) {
+ if (ownerAddress == null || !isUsableOwner(ownerAddress)) {
throw Exception(
- "Could not derive owner address distinct from collateral address.",
+ "Could not derive owner address distinct from collateral and payout "
+ "addresses.",
);
}
Why this scored 42/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.