sign_tx/sign_psbt: give a more useful error message for invalid output amounts
What changed, and why it matters
This commit improves error handling in Blockstream Jade's transaction signing code. Previously, if the total output amount of a Bitcoin transaction was too large to be valid, the device would trigger an internal assertion failure (JADE_WALLY_VERIFY). Now it returns a clear 'bad parameters' error to the user instead. This is primarily a robustness and user-experience improvement; it may also prevent a potential denial-of-service or confusing error state when signing malformed transactions.
Treat as a low-severity hardening fix. Review whether any other JADE_WALLY_VERIFY calls in signing paths should similarly be converted to explicit error returns to avoid assertion-triggering inputs. No urgent user action required.
Security signals we found
Replaces JADE_WALLY_VERIFY assertion with explicit error handling for invalid transaction output amounts
Returns controlled CBOR_RPC_BAD_PARAMETERS instead of potentially aborting on malformed input
Adds message-load logic to ensure error reply can be sent during anti-exfil signature flow
Applies to both PSBT and raw transaction signing paths
Evidence from the diff
In sign_psbt.c and sign_tx.c, the code previously called JADE_WALLY_VERIFY(wally_tx_get_total_output_satoshi(…)), which aborts/verifies on non-WALLY_OK return. The patch changes this to check the return value explicitly. If wally_tx_get_total_output_satoshi returns non-WALLY_OK (documented in libwally as meaning total outputs exceed the maximum allowed, i.e., > MAX_MONEY), the code now sets errmsg to ‘Total output amounts exceed maximum’ and returns CBOR_RPC_BAD_PARAMETERS. For sign_tx.c, it also ensures the incoming message is loaded when using anti-exfil signatures so the rejection can be sent back. This is a defensive change: it converts a hard assertion/verify failure into a controlled RPC error response.
Changed components
main/process/sign_psbt.cmain/process/sign_tx.cBitcoin transaction signing flowAnti-exfil (AE) signature error-response pathInspect captured patch +15 / −4
### main/process/sign_psbt.c
@@ -1023,8 +1023,12 @@ int sign_psbt(jade_process_t* process, CborValue* params, const network_t networ
}
} else {
// Bitcoin: Sanity check amounts
- uint64_t output_amount;
- JADE_WALLY_VERIFY(wally_tx_get_total_output_satoshi(tx, &output_amount));
+ uint64_t output_amount = 0;
+ if (wally_tx_get_total_output_satoshi(tx, &output_amount) != WALLY_OK) {
+ *errmsg = "Total output amounts exceed maximum";
+ retval = CBOR_RPC_BAD_PARAMETERS;
+ goto cleanup;
+ }
if (output_amount > input_amount) {
*errmsg = "Total input amounts less than total output amounts";
retval = CBOR_RPC_BAD_PARAMETERS;
### main/process/sign_tx.c
@@ -842,8 +842,15 @@ static void sign_tx_impl(jade_process_t* process, const bool for_liquid)
if (!for_liquid) {
// Bitcoin: Sanity check amounts
- uint64_t output_amount;
- JADE_WALLY_VERIFY(wally_tx_get_total_output_satoshi(tx, &output_amount));
+ uint64_t output_amount = 0;
+ if (wally_tx_get_total_output_satoshi(tx, &output_amount) != WALLY_OK) {
+ // If using ae-signatures, we need to load the message to send the error back on
+ if (use_ae_signatures) {
+ jade_process_load_in_message(process, true);
+ }
+ jade_process_reject_message(process, CBOR_RPC_BAD_PARAMETERS, "Total output amounts exceed maximum");
+ goto cleanup;
+ }
if (output_amount > input_amount) {
// If using ae-signatures, we need to load the message to send the error back on
if (use_ae_signatures) {Why this scored 32/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.