Line data Source code
1 : // Copyright (c) 2009-2014 The Bitcoin developers 2 : // Copyright (c) 2015-2021 The PIVX Core developers 3 : // Distributed under the MIT/X11 software license, see the accompanying 4 : // file COPYING or http://www.opensource.org/licenses/mit-license.php. 5 : 6 : #include "core_io.h" 7 : 8 : #include "primitives/block.h" 9 : #include "primitives/transaction.h" 10 : #include "script/script.h" 11 : #include "serialize.h" 12 : #include "streams.h" 13 : #include "util/system.h" 14 : #include "utilstrencodings.h" 15 : #include "version.h" 16 : 17 : #include <boost/algorithm/string/classification.hpp> 18 : #include <boost/algorithm/string/replace.hpp> 19 : #include <boost/algorithm/string/split.hpp> 20 : 21 : #include <univalue.h> 22 : 23 2190 : CScript ParseScript(std::string s) 24 : { 25 2190 : CScript result; 26 : 27 2190 : static std::map<std::string, opcodetype> mapOpNames; 28 : 29 2190 : if (mapOpNames.empty()) { 30 1176 : for (int op = 0; op <= OP_ZEROCOINSPEND; op++) { 31 : // Allow OP_RESERVED to get into mapOpNames 32 1170 : if (op < OP_NOP && op != OP_RESERVED) 33 618 : continue; 34 : 35 594 : const char* name = GetOpName(static_cast<opcodetype>(op)); 36 594 : if (strcmp(name, "OP_UNKNOWN") == 0) 37 42 : continue; 38 1104 : std::string strName(name); 39 552 : mapOpNames[strName] = static_cast<opcodetype>(op); 40 : // Convenience: OP_ADD and just ADD are both recognized: 41 552 : boost::algorithm::replace_first(strName, "OP_", ""); 42 552 : mapOpNames[strName] = static_cast<opcodetype>(op); 43 : } 44 : } 45 : 46 2190 : std::vector<std::string> words; 47 2190 : boost::algorithm::split(words, s, boost::algorithm::is_any_of(" \t\n"), boost::algorithm::token_compress_on); 48 : 49 12565 : for (std::vector<std::string>::const_iterator w = words.begin(); w != words.end(); ++w) { 50 10375 : if (w->empty()) { 51 : // Empty string, ignore. (boost::split given '' will return one word) 52 10267 : } else if (std::all_of(w->begin(), w->end(), ::IsDigit) || 53 6263 : (w->front() == '-' && w->size() > 1 && std::all_of(w->begin()+1, w->end(), ::IsDigit))) { 54 : // Number 55 4084 : int64_t n = atoi64(*w); 56 10375 : result << n; 57 7628 : } else if (w->substr(0,2) == "0x" && w->size() > 2 && IsHex(std::string(w->begin()+2, w->end()))) { 58 : // Raw hex data, inserted NOT pushed onto stack: 59 2890 : std::vector<unsigned char> raw = ParseHex(std::string(w->begin() + 2, w->end())); 60 2890 : result.insert(result.end(), raw.begin(), raw.end()); 61 4738 : } else if (w->size() >= 2 && w->front() == '\'' && w->back() == '\'') { 62 : // Single-quoted string, pushed as data. NOTE: this is poor-man's 63 : // parsing, spaces/tabs/newlines in single-quoted strings won't work. 64 2488 : std::vector<unsigned char> value(w->begin() + 1, w->end() - 1); 65 1244 : result << value; 66 3494 : } else if (mapOpNames.count(*w)) { 67 : // opcode, e.g. OP_ADD or ADD: 68 3494 : result << mapOpNames[*w]; 69 : } else { 70 0 : throw std::runtime_error("script parse error"); 71 : } 72 : } 73 : 74 2190 : return result; 75 : } 76 : 77 108698 : bool DecodeHexTx(CMutableTransaction& tx, const std::string& strHexTx) 78 : { 79 108698 : if (!IsHex(strHexTx)) 80 : return false; 81 : 82 217394 : std::vector<unsigned char> txData(ParseHex(strHexTx)); 83 217392 : CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION); 84 108696 : try { 85 108698 : ssData >> tx; 86 2 : } catch (const std::exception&) { 87 2 : return false; 88 : } 89 : 90 : return true; 91 : } 92 : 93 50 : bool DecodeHexBlk(CBlock& block, const std::string& strHexBlk) 94 : { 95 50 : if (!IsHex(strHexBlk)) 96 : return false; 97 : 98 100 : std::vector<unsigned char> blockData(ParseHex(strHexBlk)); 99 100 : CDataStream ssBlock(blockData, SER_NETWORK, PROTOCOL_VERSION); 100 50 : try { 101 50 : ssBlock >> block; 102 0 : } catch (const std::exception&) { 103 0 : return false; 104 : } 105 : 106 : return true; 107 : } 108 : 109 1 : uint256 ParseHashUV(const UniValue& v, const std::string& strName) 110 : { 111 1 : std::string strHex; 112 1 : if (v.isStr()) 113 1 : strHex = v.getValStr(); 114 2 : return ParseHashStr(strHex, strName); // Note: ParseHashStr("") throws a std::runtime_error 115 : } 116 : 117 3 : uint256 ParseHashStr(const std::string& strHex, const std::string& strName) 118 : { 119 3 : if (!IsHex(strHex)) // Note: IsHex("") is false 120 0 : throw std::runtime_error(strName + " must be hexadecimal string (not '" + strHex + "')"); 121 : 122 3 : uint256 result; 123 3 : result.SetHex(strHex); 124 3 : return result; 125 : } 126 : 127 20 : bool ParseHashStr(const std::string& strReq, uint256& v) 128 : { 129 20 : if (!IsHex(strReq) || (strReq.size() != 64)) 130 : return false; 131 : 132 20 : v.SetHex(strReq); 133 20 : return true; 134 : } 135 : 136 1 : std::vector<unsigned char> ParseHexUV(const UniValue& v, const std::string& strName) 137 : { 138 1 : std::string strHex; 139 1 : if (v.isStr()) 140 1 : strHex = v.getValStr(); 141 1 : if (!IsHex(strHex)) 142 0 : throw std::runtime_error(strName + " must be hexadecimal string (not '" + strHex + "')"); 143 2 : return ParseHex(strHex); 144 : }