| 126 | } |
| 127 | |
| 128 | static bool DecodeTx(CMutableTransaction& tx, const std::vector<unsigned char>& tx_data, bool try_no_witness, bool try_witness) |
| 129 | { |
| 130 | // General strategy: |
| 131 | // - Decode both with extended serialization (which interprets the 0x0001 tag as a marker for |
| 132 | // the presence of witnesses) and with legacy serialization (which interprets the tag as a |
| 133 | // 0-input 1-output incomplete transaction). |
| 134 | // - Restricted by try_no_witness (which disables legacy if false) and try_witness (which |
| 135 | // disables extended if false). |
| 136 | // - Ignore serializations that do not fully consume the hex string. |
| 137 | // - If neither succeeds, fail. |
| 138 | // - If only one succeeds, return that one. |
| 139 | // - If both decode attempts succeed: |
| 140 | // - If only one passes the CheckTxScriptsSanity check, return that one. |
| 141 | // - If neither or both pass CheckTxScriptsSanity, return the extended one. |
| 142 | |
| 143 | CMutableTransaction tx_extended, tx_legacy; |
| 144 | bool ok_extended = false, ok_legacy = false; |
| 145 | |
| 146 | // Try decoding with extended serialization support, and remember if the result successfully |
| 147 | // consumes the entire input. |
| 148 | if (try_witness) { |
| 149 | CDataStream ssData(tx_data, SER_NETWORK, PROTOCOL_VERSION); |
| 150 | try { |
| 151 | ssData >> tx_extended; |
| 152 | if (ssData.empty()) ok_extended = true; |
| 153 | } catch (const std::exception&) { |
| 154 | // Fall through. |
| 155 | } |
| 156 | } |
| 157 | |
| 158 | // Optimization: if extended decoding succeeded and the result passes CheckTxScriptsSanity, |
| 159 | // don't bother decoding the other way. |
| 160 | if (ok_extended && CheckTxScriptsSanity(tx_extended)) { |
| 161 | tx = std::move(tx_extended); |
| 162 | return true; |
| 163 | } |
| 164 | |
| 165 | // Try decoding with legacy serialization, and remember if the result successfully consumes the entire input. |
| 166 | if (try_no_witness) { |
| 167 | CDataStream ssData(tx_data, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS); |
| 168 | try { |
| 169 | ssData >> tx_legacy; |
| 170 | if (ssData.empty()) ok_legacy = true; |
| 171 | } catch (const std::exception&) { |
| 172 | // Fall through. |
| 173 | } |
| 174 | } |
| 175 | |
| 176 | // If legacy decoding succeeded and passes CheckTxScriptsSanity, that's our answer, as we know |
| 177 | // at this point that extended decoding either failed or doesn't pass the sanity check. |
| 178 | if (ok_legacy && CheckTxScriptsSanity(tx_legacy)) { |
| 179 | tx = std::move(tx_legacy); |
| 180 | return true; |
| 181 | } |
| 182 | |
| 183 | // If extended decoding succeeded, and neither decoding passes sanity, return the extended one. |
| 184 | if (ok_extended) { |
| 185 | tx = std::move(tx_extended); |
no test coverage detected