Validate PartiallySignedTransaction after decoding - #2093
Conversation
|
Thanks for this — the approach looks right to me. I checked that A few small things:
Unrelated to this diff, but the same bug class as #2069 if you feel like folding it in: One process note: this branch is based on |
Wallet RPC methods and CLI commands accept a hex-encoded PartiallySignedTransaction and decode it with SCALE, which bypasses the invariants that PartiallySignedTransaction::new enforces. A malformed but still decodable transaction could then make the wallet panic, e.g. on a witness/input count mismatch. Call ensure_consistency right after decoding in GenericTransaction::decode_from_untagged_bytes, the shared decode path used by account_sign_raw_transaction and transaction_inspect, so such input is rejected with a proper error instead. The Basic level is used so that transactions that are still being assembled are not rejected.
Both callers of decode_from_untagged_bytes mapped the error to a unit InvalidRawTransaction variant, so the reason a transaction was rejected never reached the user and an inconsistent transaction looked the same as malformed hex. Give the variant the inner error instead, so the message says which count did not match. Also correct the comment above the Basic check. Basic does verify that the input utxo count matches the input count, the entries are just allowed to be None, so only the additional info part of the original wording was right. Add #[source] to the new error field so Error::source() returns the inner error rather than None.
3f68397 to
fbf262e
Compare
|
@erubboli Rebased all four onto master. I folded the error into the existing Left the client side expects for a follow-up against #2069. There are two of them there rather than one. |
Problem
Wallet RPC methods and CLI commands that accept a
PartiallySignedTransactiondecode it from bytes with SCALE, which skips the checks thatPartiallySignedTransaction::newperforms. A malformed but still decodable transaction (for example one whose witness count does not match the number of inputs) can therefore reach the wallet and make it panic instead of returning an error.Fix
Call
ensure_consistencyimmediately after decoding inGenericTransaction::decode_from_untagged_bytes, the shared path used byaccount_sign_raw_transactionandtransaction_inspect(and the CLI commands that call them). A newGenericTransactionError::InconsistentPartiallySignedTransactionvariant is returned on failure.The
Basicconsistency level is used on purpose: it enforces the structural invariants that prevent the panics, while still accepting partial transactions that are legitimately incomplete during signing. UsingWithAdditionalInfohere would reject those and also break the existing decode test.Tests
Added a unit test that feeds a hand-encoded, inconsistent
PartiallySignedTransactionthrough the decode path and asserts it is rejected. The existing tests still pass and clippy is clean for the changed crate.Closes #2069