core_read.cpp
1 // Copyright (c) 2009-2022 The Bitcoin Core developers 2 // Distributed under the MIT software license, see the accompanying 3 // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 5 #include <core_io.h> 6 7 #include <primitives/block.h> 8 #include <primitives/transaction.h> 9 #include <script/script.h> 10 #include <script/sign.h> 11 #include <serialize.h> 12 #include <streams.h> 13 #include <util/result.h> 14 #include <util/strencodings.h> 15 16 #include <algorithm> 17 #include <string> 18 19 using util::SplitString; 20 21 namespace { 22 class OpCodeParser 23 { 24 private: 25 std::map<std::string, opcodetype> mapOpNames; 26 27 public: 28 OpCodeParser() 29 { 30 for (unsigned int op = 0; op <= MAX_OPCODE; ++op) { 31 // Allow OP_RESERVED to get into mapOpNames 32 if (op < OP_NOP && op != OP_RESERVED) { 33 continue; 34 } 35 36 std::string strName = GetOpName(static_cast<opcodetype>(op)); 37 if (strName == "OP_UNKNOWN") { 38 continue; 39 } 40 mapOpNames[strName] = static_cast<opcodetype>(op); 41 // Convenience: OP_ADD and just ADD are both recognized: 42 if (strName.starts_with("OP_")) { 43 mapOpNames[strName.substr(3)] = static_cast<opcodetype>(op); 44 } 45 } 46 } 47 opcodetype Parse(const std::string& s) const 48 { 49 auto it = mapOpNames.find(s); 50 if (it == mapOpNames.end()) throw std::runtime_error("script parse error: unknown opcode"); 51 return it->second; 52 } 53 }; 54 55 opcodetype ParseOpCode(const std::string& s) 56 { 57 static const OpCodeParser ocp; 58 return ocp.Parse(s); 59 } 60 61 } // namespace 62 63 CScript ParseScript(const std::string& s) 64 { 65 CScript result; 66 67 std::vector<std::string> words = SplitString(s, " \t\n"); 68 69 for (const std::string& w : words) { 70 if (w.empty()) { 71 // Empty string, ignore. (SplitString doesn't combine multiple separators) 72 } else if (std::all_of(w.begin(), w.end(), ::IsDigit) || 73 (w.front() == '-' && w.size() > 1 && std::all_of(w.begin() + 1, w.end(), ::IsDigit))) 74 { 75 // Number 76 const auto num{ToIntegral<int64_t>(w)}; 77 78 // limit the range of numbers ParseScript accepts in decimal 79 // since numbers outside -0xFFFFFFFF...0xFFFFFFFF are illegal in scripts 80 if (!num.has_value() || num > int64_t{0xffffffff} || num < -1 * int64_t{0xffffffff}) { 81 throw std::runtime_error("script parse error: decimal numeric value only allowed in the " 82 "range -0xFFFFFFFF...0xFFFFFFFF"); 83 } 84 85 result << num.value(); 86 } else if (w.starts_with("0x") && w.size() > 2 && IsHex(std::string(w.begin() + 2, w.end()))) { 87 // Raw hex data, inserted NOT pushed onto stack: 88 std::vector<unsigned char> raw = ParseHex(std::string(w.begin() + 2, w.end())); 89 result.insert(result.end(), raw.begin(), raw.end()); 90 } else if (w.size() >= 2 && w.front() == '\'' && w.back() == '\'') { 91 // Single-quoted string, pushed as data. NOTE: this is poor-man's 92 // parsing, spaces/tabs/newlines in single-quoted strings won't work. 93 std::vector<unsigned char> value(w.begin() + 1, w.end() - 1); 94 result << value; 95 } else { 96 // opcode, e.g. OP_ADD or ADD: 97 result << ParseOpCode(w); 98 } 99 } 100 101 return result; 102 } 103 104 // Check that all of the input and output scripts of a transaction contains valid opcodes 105 static bool CheckTxScriptsSanity(const CMutableTransaction& tx) 106 { 107 // Check input scripts for non-coinbase txs 108 if (!CTransaction(tx).IsCoinBase()) { 109 for (unsigned int i = 0; i < tx.vin.size(); i++) { 110 if (!tx.vin[i].scriptSig.HasValidOps() || tx.vin[i].scriptSig.size() > MAX_SCRIPT_SIZE) { 111 return false; 112 } 113 } 114 } 115 // Check output scripts 116 for (unsigned int i = 0; i < tx.vout.size(); i++) { 117 if (!tx.vout[i].scriptPubKey.HasValidOps() || tx.vout[i].scriptPubKey.size() > MAX_SCRIPT_SIZE) { 118 return false; 119 } 120 } 121 122 return true; 123 } 124 125 static bool DecodeTx(CMutableTransaction& tx, const std::vector<unsigned char>& tx_data, bool try_no_witness, bool try_witness) 126 { 127 // General strategy: 128 // - Decode both with extended serialization (which interprets the 0x0001 tag as a marker for 129 // the presence of witnesses) and with legacy serialization (which interprets the tag as a 130 // 0-input 1-output incomplete transaction). 131 // - Restricted by try_no_witness (which disables legacy if false) and try_witness (which 132 // disables extended if false). 133 // - Ignore serializations that do not fully consume the hex string. 134 // - If neither succeeds, fail. 135 // - If only one succeeds, return that one. 136 // - If both decode attempts succeed: 137 // - If only one passes the CheckTxScriptsSanity check, return that one. 138 // - If neither or both pass CheckTxScriptsSanity, return the extended one. 139 140 CMutableTransaction tx_extended, tx_legacy; 141 bool ok_extended = false, ok_legacy = false; 142 143 // Try decoding with extended serialization support, and remember if the result successfully 144 // consumes the entire input. 145 if (try_witness) { 146 DataStream ssData(tx_data); 147 try { 148 ssData >> TX_WITH_WITNESS(tx_extended); 149 if (ssData.empty()) ok_extended = true; 150 } catch (const std::exception&) { 151 // Fall through. 152 } 153 } 154 155 // Optimization: if extended decoding succeeded and the result passes CheckTxScriptsSanity, 156 // don't bother decoding the other way. 157 if (ok_extended && CheckTxScriptsSanity(tx_extended)) { 158 tx = std::move(tx_extended); 159 return true; 160 } 161 162 // Try decoding with legacy serialization, and remember if the result successfully consumes the entire input. 163 if (try_no_witness) { 164 DataStream ssData(tx_data); 165 try { 166 ssData >> TX_NO_WITNESS(tx_legacy); 167 if (ssData.empty()) ok_legacy = true; 168 } catch (const std::exception&) { 169 // Fall through. 170 } 171 } 172 173 // If legacy decoding succeeded and passes CheckTxScriptsSanity, that's our answer, as we know 174 // at this point that extended decoding either failed or doesn't pass the sanity check. 175 if (ok_legacy && CheckTxScriptsSanity(tx_legacy)) { 176 tx = std::move(tx_legacy); 177 return true; 178 } 179 180 // If extended decoding succeeded, and neither decoding passes sanity, return the extended one. 181 if (ok_extended) { 182 tx = std::move(tx_extended); 183 return true; 184 } 185 186 // If legacy decoding succeeded and extended didn't, return the legacy one. 187 if (ok_legacy) { 188 tx = std::move(tx_legacy); 189 return true; 190 } 191 192 // If none succeeded, we failed. 193 return false; 194 } 195 196 bool DecodeHexTx(CMutableTransaction& tx, const std::string& hex_tx, bool try_no_witness, bool try_witness) 197 { 198 if (!IsHex(hex_tx)) { 199 return false; 200 } 201 202 std::vector<unsigned char> txData(ParseHex(hex_tx)); 203 return DecodeTx(tx, txData, try_no_witness, try_witness); 204 } 205 206 bool DecodeHexBlockHeader(CBlockHeader& header, const std::string& hex_header) 207 { 208 if (!IsHex(hex_header)) return false; 209 210 const std::vector<unsigned char> header_data{ParseHex(hex_header)}; 211 DataStream ser_header{header_data}; 212 try { 213 ser_header >> header; 214 } catch (const std::exception&) { 215 return false; 216 } 217 return true; 218 } 219 220 bool DecodeHexBlk(CBlock& block, const std::string& strHexBlk) 221 { 222 if (!IsHex(strHexBlk)) 223 return false; 224 225 std::vector<unsigned char> blockData(ParseHex(strHexBlk)); 226 DataStream ssBlock(blockData); 227 try { 228 ssBlock >> TX_WITH_WITNESS(block); 229 } 230 catch (const std::exception&) { 231 return false; 232 } 233 234 return true; 235 } 236 237 util::Result<int> SighashFromStr(const std::string& sighash) 238 { 239 static const std::map<std::string, int> map_sighash_values = { 240 {std::string("DEFAULT"), int(SIGHASH_DEFAULT)}, 241 {std::string("ALL"), int(SIGHASH_ALL)}, 242 {std::string("ALL|ANYONECANPAY"), int(SIGHASH_ALL|SIGHASH_ANYONECANPAY)}, 243 {std::string("NONE"), int(SIGHASH_NONE)}, 244 {std::string("NONE|ANYONECANPAY"), int(SIGHASH_NONE|SIGHASH_ANYONECANPAY)}, 245 {std::string("SINGLE"), int(SIGHASH_SINGLE)}, 246 {std::string("SINGLE|ANYONECANPAY"), int(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY)}, 247 }; 248 const auto& it = map_sighash_values.find(sighash); 249 if (it != map_sighash_values.end()) { 250 return it->second; 251 } else { 252 return util::Error{Untranslated("'" + sighash + "' is not a valid sighash parameter.")}; 253 } 254 }