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