diff --git a/src/core_read.cpp b/src/core_read.cpp index ae322671c..680cda6bc 100644 --- a/src/core_read.cpp +++ b/src/core_read.cpp @@ -1,165 +1,177 @@ // Copyright (c) 2009-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "core_io.h" #include "primitives/block.h" #include "primitives/transaction.h" #include "script/script.h" #include "serialize.h" #include "streams.h" #include "util.h" #include "utilstrencodings.h" #include "version.h" #include #include #include #include #include CScript ParseScript(const std::string &s) { CScript result; static std::map mapOpNames; if (mapOpNames.empty()) { for (int op = 0; op < FIRST_UNDEFINED_OP_VALUE; op++) { // ignore all "PUSHDATA" ops, but dont ignore OP_RESERVED if (op < OP_NOP && op != OP_RESERVED) { continue; } const char *name = GetOpName((opcodetype)op); if (strcmp(name, "OP_UNKNOWN") == 0) { continue; } std::string strName(name); mapOpNames[strName] = (opcodetype)op; // Convenience: OP_ADD and just ADD are both recognized: boost::algorithm::replace_first(strName, "OP_", ""); mapOpNames[strName] = (opcodetype)op; } } std::vector words; boost::algorithm::split(words, s, boost::algorithm::is_any_of(" \t\n"), boost::algorithm::token_compress_on); - for (std::vector::const_iterator w = words.begin(); - w != words.end(); ++w) { - if (w->empty()) { + for (const auto &w : words) { + if (w.empty()) { // Empty string, ignore. (boost::split given '' will return one // word) - } else if (all(*w, boost::algorithm::is_digit()) || - (boost::algorithm::starts_with(*w, "-") && - all(std::string(w->begin() + 1, w->end()), - boost::algorithm::is_digit()))) { + continue; + } + + if (all(w, boost::algorithm::is_digit()) || + (boost::algorithm::starts_with(w, "-") && + all(std::string(w.begin() + 1, w.end()), + boost::algorithm::is_digit()))) { // Number - int64_t n = atoi64(*w); + int64_t n = atoi64(w); result << n; - } else if (boost::algorithm::starts_with(*w, "0x") && - (w->begin() + 2 != w->end())) { - if (IsHex(std::string(w->begin() + 2, w->end()))) { - // Raw hex data, inserted NOT pushed onto stack: - std::vector raw = - ParseHex(std::string(w->begin() + 2, w->end())); - result.insert(result.end(), raw.begin(), raw.end()); - } else { + continue; + } + + if (boost::algorithm::starts_with(w, "0x") && + (w.begin() + 2 != w.end())) { + if (!IsHex(std::string(w.begin() + 2, w.end()))) { // Should only arrive here for improperly formatted hex values throw std::runtime_error("Hex numbers expected to be formatted " "in full-byte chunks (ex: 0x00 " "instead of 0x0)"); } - } else if (w->size() >= 2 && boost::algorithm::starts_with(*w, "'") && - boost::algorithm::ends_with(*w, "'")) { + + // Raw hex data, inserted NOT pushed onto stack: + std::vector raw = + ParseHex(std::string(w.begin() + 2, w.end())); + result.insert(result.end(), raw.begin(), raw.end()); + continue; + } + + if (w.size() >= 2 && boost::algorithm::starts_with(w, "'") && + boost::algorithm::ends_with(w, "'")) { // Single-quoted string, pushed as data. NOTE: this is poor-man's // parsing, spaces/tabs/newlines in single-quoted strings won't // work. - std::vector value(w->begin() + 1, w->end() - 1); + std::vector value(w.begin() + 1, w.end() - 1); result << value; - } else if (mapOpNames.count(*w)) { + continue; + } + + if (mapOpNames.count(w)) { // opcode, e.g. OP_ADD or ADD: - result << mapOpNames[*w]; - } else { - throw std::runtime_error("Error parsing script: " + s); + result << mapOpNames[w]; + continue; } + + throw std::runtime_error("Error parsing script: " + s); } return result; } bool DecodeHexTx(CMutableTransaction &tx, const std::string &strHexTx) { if (!IsHex(strHexTx)) { return false; } std::vector txData(ParseHex(strHexTx)); CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION); try { ssData >> tx; if (!ssData.empty()) { return false; } } catch (const std::exception &) { return false; } return true; } bool DecodeHexBlk(CBlock &block, const std::string &strHexBlk) { if (!IsHex(strHexBlk)) { return false; } std::vector blockData(ParseHex(strHexBlk)); CDataStream ssBlock(blockData, SER_NETWORK, PROTOCOL_VERSION); try { ssBlock >> block; } catch (const std::exception &) { return false; } return true; } uint256 ParseHashUV(const UniValue &v, const std::string &strName) { std::string strHex; if (v.isStr()) { strHex = v.getValStr(); } // Note: ParseHashStr("") throws a runtime_error return ParseHashStr(strHex, strName); } uint256 ParseHashStr(const std::string &strHex, const std::string &strName) { if (!IsHex(strHex)) { // Note: IsHex("") is false throw std::runtime_error( strName + " must be hexadecimal string (not '" + strHex + "')"); } uint256 result; result.SetHex(strHex); return result; } std::vector ParseHexUV(const UniValue &v, const std::string &strName) { std::string strHex; if (v.isStr()) { strHex = v.getValStr(); } if (!IsHex(strHex)) { throw std::runtime_error( strName + " must be hexadecimal string (not '" + strHex + "')"); } return ParseHex(strHex); }