What changed, and why it matters
This commit fixes a fee-calculation bug in the Spark privacy-coin minting code. The wallet was estimating transaction fees using a virtual size that was too small, which could lead to transactions paying too little in network fees. Such underpaid transactions may get stuck, fail to confirm, or be rejected by the network. The patch adds a 10-byte safety buffer to the size estimate and adds a debug log line to make future fee mismatches easier to spot.
Treat as a routine bugfix with low security severity. Users relying on Spark mints should update to ensure mint transactions are not underpaid. Review whether a fixed 10-byte buffer is adequate for all transaction variants and consider replacing the heuristic with a proper vsize estimator.
Security signals we found
Transaction fee under-estimation in privacy (Spark) mint path
Potential transaction stuck/failure due to insufficient fee
Defensive size buffer added to fee calculation
Debug logging added for fee/size mismatch diagnosis
Evidence from the diff
In lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart, the Spark mint fee estimation previously called estimateTxFee with vSize: nBytes directly. The patch introduces a constant nBytesBuffer = 10 and passes nBytes + nBytesBuffer to estimateTxFee, increasing the fee reserve. It also logs nFeeRet and data.vSize before the existing underpayment check. The change is a small, defensive buffer rather than a redesign of fee estimation, as noted by the inline comment ‘One day we’ll do this properly’.
Changed components
lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dartSpark mint transaction fee estimationInspect captured patch +6 / −1
diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart
index 2fa4637..5a2a025 100644
--- a/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart
+++ b/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart
@@ -1741,8 +1741,12 @@ mixin SparkInterface<T extends ElectrumXCurrencyInterface>
throw Exception("Transaction too large");
}
+ const nBytesBuffer = 10;
final nFeeNeeded = BigInt.from(
- estimateTxFee(vSize: nBytes, feeRatePerKB: feesObject.medium),
+ estimateTxFee(
+ vSize: nBytes + nBytesBuffer,
+ feeRatePerKB: feesObject.medium,
+ ),
); // One day we'll do this properly
if (nFeeRet >= nFeeNeeded) {
@@ -1993,6 +1997,7 @@ mixin SparkInterface<T extends ElectrumXCurrencyInterface>
),
);
+ Logging.instance.i("nFeeRet=$nFeeRet, vSize=${data.vSize}");
if (nFeeRet.toInt() < data.vSize!) {
Logging.instance.w(
"Spark mint transaction failed: $nFeeRet is less than ${data.vSize}",
Why this scored 35/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.