fix(bitcoin): Ensure non-negative amounts in transaction processing#4741
fix(bitcoin): Ensure non-negative amounts in transaction processing#4741sergei-boiko-trustwallet wants to merge 11 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR hardens UTXO-chain transaction processing by enforcing non-negative monetary amounts and propagating conversion failures as structured signing/planning errors across the C++ (Bitcoin/Zen/Decred) and Rust (tw_utxo, tw_bitcoin, tw_decred, tw_zcash) stacks.
Changes:
- Added/centralized non-negative amount validation in C++ Bitcoin-derived modules (
assertValidAmount) and applied it at key Proto parsing / output construction points. - Refactored Rust UTXO amount handling to use unsigned
Amount(u64) and expandedtry_into()-based error propagation for proto builders, planners, signers, and fee policy parsing. - Updated tests and constants to match the new error mapping and unsigned amount types.
Reviewed changes
Copilot reviewed 28 out of 28 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/Zen/TransactionBuilder.h | Validates output amounts as non-negative before script/output construction. |
| src/Decred/TransactionOutput.h | Enforces non-negative output value at construction time. |
| src/Bitcoin/UTXO.h | Validates protobuf UTXO amounts on construction. |
| src/Bitcoin/TransactionPlan.h | Validates plan amounts/fee/change are non-negative when built from protobuf. |
| src/Bitcoin/SigningInput.cpp | Validates protobuf-provided amounts (amount, byte fee, extra outputs) are non-negative. |
| src/Bitcoin/Amount.h | Introduces assertValidAmount helper throwing on negative amounts. |
| rust/tw_tests/tests/chains/bitcoin/bitcoin_plan/plan_exact_error.rs | Updates expected planner error for negative output amounts. |
| rust/frameworks/tw_utxo/tests/build_tx.rs | Migrates fee-rate/expected fee types to u64 to match unsigned amounts. |
| rust/frameworks/tw_utxo/src/transaction/unsigned_transaction.rs | Computes totals using u64 accumulation with checked arithmetic. |
| rust/frameworks/tw_utxo/src/transaction/transaction_sighash/legacy_sighash.rs | Updates documentation around default output value sentinel under unsigned Amount. |
| rust/frameworks/tw_utxo/src/transaction/transaction_parts.rs | Changes core Amount type to u64 and updates documentation. |
| rust/frameworks/tw_utxo/src/transaction/standard_transaction/mod.rs | Replaces -1 default output value with u64::MAX and documents SIGHASH_SINGLE behavior. |
| rust/chains/tw_zcash/src/modules/signing_request.rs | Rejects negative fee_per_vb via try_into() + contextual error. |
| rust/chains/tw_zcash/src/modules/protobuf_builder.rs | Makes tx→proto conversion fallible; validates sapling value balance conversion. |
| rust/chains/tw_zcash/src/modules/pczt_request/utxo_pczt.rs | Simplifies amount handling now that PCZT transparent values are u64. |
| rust/chains/tw_zcash/src/modules/pczt_request/output_pczt.rs | Simplifies output value handling now that PCZT transparent values are u64. |
| rust/chains/tw_decred/src/modules/protobuf_builder.rs | Makes input/output proto building fallible with amount conversions. |
| rust/chains/tw_bitcoin/src/modules/tx_builder/utxo_protobuf.rs | Replaces manual negative checks with try_into() + contextual error mapping. |
| rust/chains/tw_bitcoin/src/modules/tx_builder/output_protobuf.rs | Replaces manual negative checks with try_into() + contextual error mapping. |
| rust/chains/tw_bitcoin/src/modules/signing_request/standard_signing_request.rs | Validates dust threshold and fee policy inputs via try_into() conversions. |
| rust/chains/tw_bitcoin/src/modules/signer.rs | Propagates fallible tx→proto conversion and validates fee conversion. |
| rust/chains/tw_bitcoin/src/modules/psbt_request/utxo_psbt.rs | Removes now-unneeded amount conversion for u64 PSBT amounts. |
| rust/chains/tw_bitcoin/src/modules/psbt_request/output_psbt.rs | Removes now-unneeded amount conversion for u64 PSBT outputs. |
| rust/chains/tw_bitcoin/src/modules/protobuf_builder/standard_protobuf_builder.rs | Makes tx→proto conversion fallible and validates output value conversion. |
| rust/chains/tw_bitcoin/src/modules/protobuf_builder/mod.rs | Updates ProtobufBuilder trait to return SigningResult. |
| rust/chains/tw_bitcoin/src/modules/planner/psbt_planner.rs | Validates plan numeric fields via try_into() conversions (non-negative/fit checks). |
| rust/chains/tw_bitcoin/src/modules/planner/mod.rs | Validates planned output values and plan totals via try_into() conversions. |
| rust/chains/tw_bitcoin/src/modules/compiler.rs | Propagates fallible tx→proto conversion and validates fee conversion. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Binary size comparison➡️ aarch64-apple-ios: - 14.36 MB
+ 14.38 MB +19 KB➡️ aarch64-apple-ios-sim: - 14.37 MB
+ 14.39 MB +20 KB➡️ aarch64-linux-android: - 18.81 MB
+ 18.83 MB +30 KB➡️ armv7-linux-androideabi: - 16.23 MB
+ 16.26 MB +32 KB➡️ wasm32-unknown-emscripten: - 13.72 MB
+ 13.75 MB +30 KB |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 58 out of 58 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
… in transaction processing
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 60 out of 60 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…ount calculations
tw-davidkim
left a comment
There was a problem hiding this comment.
Should we also wrap the fixed_dust_threshold ? I see it's in signed integer format (Bitcoin signing input).
91f0b5c
This pull request strengthens type safety and error handling for transaction value conversions across Bitcoin, Decred, and Zcash modules. The main goal is to ensure that all monetary values (inputs, outputs, fees, etc.) are properly checked and converted, preventing negative or out-of-range values from propagating through the codebase. This is achieved by consistently using
try_into()with contextual error mapping and updating relevant method signatures to returnSigningResultfor better error propagation.Key changes by theme:
Improved Type Safety and Error Handling for Value Conversions
Replaced direct assignments of transaction amounts (inputs, outputs, fees, etc.) with
try_into()conversions and mapped errors using.tw_err(...)and.context(...)for detailed error reporting in Bitcoin and Decred modules. This affects planners, signers, protobuf builders, and transaction builders.Updated method signatures in protobuf builders and related functions (e.g.,
tx_to_proto,tx_input_to_proto,tx_output_to_proto) to returnSigningResult<T>instead of plain values, ensuring errors are properly propagated up the call stack.Refactoring and Clean-up
Consistency Across Chains
These changes make the codebase more robust, preventing invalid transaction values from causing subtle bugs or security issues, and provide clearer error messages for debugging and user feedback.