| 152 | } |
| 153 | |
| 154 | static bool DecodeTx(CMutableTransaction& tx, const std::vector<unsigned char>& tx_data, bool try_no_witness, bool try_witness) |
| 155 | { |
| 156 | // General strategy: |
| 157 | // - Decode both with extended serialization (which interprets the 0x0001 tag as a marker for |
| 158 | // the presence of witnesses) and with legacy serialization (which interprets the tag as a |
| 159 | // 0-input 1-output incomplete transaction). |
| 160 | // - Restricted by try_no_witness (which disables legacy if false) and try_witness (which |
| 161 | // disables extended if false). |
| 162 | // - Ignore serializations that do not fully consume the hex string. |
| 163 | // - If neither succeeds, fail. |
| 164 | // - If only one succeeds, return that one. |
| 165 | // - If both decode attempts succeed: |
| 166 | // - If only one passes the CheckTxScriptsSanity check, return that one. |
| 167 | // - If neither or both pass CheckTxScriptsSanity, return the extended one. |
| 168 | |
| 169 | CMutableTransaction tx_extended, tx_legacy; |
| 170 | bool ok_extended = false, ok_legacy = false; |
| 171 | |
| 172 | // Try decoding with extended serialization support, and remember if the result successfully |
| 173 | // consumes the entire input. |
| 174 | if (try_witness) { |
| 175 | SpanReader ssData{tx_data}; |
| 176 | try { |
| 177 | ssData >> TX_WITH_WITNESS(tx_extended); |
| 178 | if (ssData.empty()) ok_extended = true; |
| 179 | } catch (const std::exception&) { |
| 180 | // Fall through. |
| 181 | } |
| 182 | } |
| 183 | |
| 184 | // Optimization: if extended decoding succeeded and the result passes CheckTxScriptsSanity, |
| 185 | // don't bother decoding the other way. |
| 186 | if (ok_extended && CheckTxScriptsSanity(tx_extended)) { |
| 187 | tx = std::move(tx_extended); |
| 188 | return true; |
| 189 | } |
| 190 | |
| 191 | // Try decoding with legacy serialization, and remember if the result successfully consumes the entire input. |
| 192 | if (try_no_witness) { |
| 193 | SpanReader ssData{tx_data}; |
| 194 | try { |
| 195 | ssData >> TX_NO_WITNESS(tx_legacy); |
| 196 | if (ssData.empty()) ok_legacy = true; |
| 197 | } catch (const std::exception&) { |
| 198 | // Fall through. |
| 199 | } |
| 200 | } |
| 201 | |
| 202 | // If legacy decoding succeeded and passes CheckTxScriptsSanity, that's our answer, as we know |
| 203 | // at this point that extended decoding either failed or doesn't pass the sanity check. |
| 204 | if (ok_legacy && CheckTxScriptsSanity(tx_legacy)) { |
| 205 | tx = std::move(tx_legacy); |
| 206 | return true; |
| 207 | } |
| 208 | |
| 209 | // If extended decoding succeeded, and neither decoding passes sanity, return the extended one. |
| 210 | if (ok_extended) { |
| 211 | tx = std::move(tx_extended); |
no test coverage detected