Line data Source code
1 : // Copyright (c) 2009-2014 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 "serialize.h"
11 : #include "streams.h"
12 : #include <univalue.h>
13 : #include "util.h"
14 : #include "utilstrencodings.h"
15 : #include "version.h"
16 :
17 : #include <boost/algorithm/string/classification.hpp>
18 : #include <boost/algorithm/string/predicate.hpp>
19 : #include <boost/algorithm/string/replace.hpp>
20 : #include <boost/algorithm/string/split.hpp>
21 : #include <boost/assign/list_of.hpp>
22 :
23 : using namespace std;
24 :
25 2203 : CScript ParseScript(const std::string& s)
26 : {
27 : CScript result;
28 :
29 2205 : static map<string, opcodetype> mapOpNames;
30 :
31 2203 : if (mapOpNames.empty())
32 : {
33 372 : for (int op = 0; op <= OP_NOP10; op++)
34 : {
35 : // Allow OP_RESERVED to get into mapOpNames
36 372 : if (op < OP_NOP && op != OP_RESERVED)
37 192 : continue;
38 :
39 180 : const char* name = GetOpName((opcodetype)op);
40 180 : if (strcmp(name, "OP_UNKNOWN") == 0)
41 : continue;
42 360 : string strName(name);
43 180 : mapOpNames[strName] = (opcodetype)op;
44 : // Convenience: OP_ADD and just ADD are both recognized:
45 180 : boost::algorithm::replace_first(strName, "OP_", "");
46 180 : mapOpNames[strName] = (opcodetype)op;
47 : }
48 : }
49 :
50 2203 : vector<string> words;
51 2203 : boost::algorithm::split(words, s, boost::algorithm::is_any_of(" \t\n"), boost::algorithm::token_compress_on);
52 :
53 29640 : for (std::vector<std::string>::const_iterator w = words.begin(); w != words.end(); ++w)
54 : {
55 20828 : if (w->empty())
56 : {
57 : // Empty string, ignore. (boost::split given '' will return one word)
58 : }
59 37203 : else if (all(*w, boost::algorithm::is_digit()) ||
60 6922 : (boost::algorithm::starts_with(*w, "-") && all(string(w->begin()+1, w->end()), boost::algorithm::is_digit())))
61 : {
62 : // Number
63 4105 : int64_t n = atoi64(*w);
64 : result << n;
65 : }
66 25391 : else if (boost::algorithm::starts_with(*w, "0x") && (w->begin()+2 != w->end()) && IsHex(string(w->begin()+2, w->end())))
67 : {
68 : // Raw hex data, inserted NOT pushed onto stack:
69 8658 : std::vector<unsigned char> raw = ParseHex(string(w->begin()+2, w->end()));
70 2886 : result.insert(result.end(), raw.begin(), raw.end());
71 : }
72 15521 : else if (w->size() >= 2 && boost::algorithm::starts_with(*w, "'") && boost::algorithm::ends_with(*w, "'"))
73 : {
74 : // Single-quoted string, pushed as data. NOTE: this is poor-man's
75 : // parsing, spaces/tabs/newlines in single-quoted strings won't work.
76 7464 : std::vector<unsigned char> value(w->begin()+1, w->end()-1);
77 1244 : result << value;
78 : }
79 7030 : else if (mapOpNames.count(*w))
80 : {
81 : // opcode, e.g. OP_ADD or ADD:
82 3515 : result << mapOpNames[*w];
83 : }
84 : else
85 : {
86 0 : throw runtime_error("script parse error");
87 : }
88 : }
89 :
90 2203 : return result;
91 : }
92 :
93 104 : bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx)
94 : {
95 104 : if (!IsHex(strHexTx))
96 : return false;
97 :
98 101 : vector<unsigned char> txData(ParseHex(strHexTx));
99 : CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
100 : try {
101 : ssData >> tx;
102 : }
103 2 : catch (const std::exception&) {
104 : return false;
105 : }
106 :
107 : return true;
108 : }
109 :
110 0 : bool DecodeHexBlk(CBlock& block, const std::string& strHexBlk)
111 : {
112 0 : if (!IsHex(strHexBlk))
113 : return false;
114 :
115 0 : std::vector<unsigned char> blockData(ParseHex(strHexBlk));
116 : CDataStream ssBlock(blockData, SER_NETWORK, PROTOCOL_VERSION);
117 : try {
118 0 : ssBlock >> block;
119 : }
120 0 : catch (const std::exception&) {
121 : return false;
122 : }
123 :
124 : return true;
125 : }
126 :
127 1 : uint256 ParseHashUV(const UniValue& v, const string& strName)
128 : {
129 : string strHex;
130 1 : if (v.isStr())
131 1 : strHex = v.getValStr();
132 2 : return ParseHashStr(strHex, strName); // Note: ParseHashStr("") throws a runtime_error
133 : }
134 :
135 1 : uint256 ParseHashStr(const std::string& strHex, const std::string& strName)
136 : {
137 1 : if (!IsHex(strHex)) // Note: IsHex("") is false
138 0 : throw runtime_error(strName+" must be hexadecimal string (not '"+strHex+"')");
139 :
140 : uint256 result;
141 1 : result.SetHex(strHex);
142 1 : return result;
143 : }
144 :
145 1 : vector<unsigned char> ParseHexUV(const UniValue& v, const string& strName)
146 : {
147 : string strHex;
148 1 : if (v.isStr())
149 1 : strHex = v.getValStr();
150 1 : if (!IsHex(strHex))
151 0 : throw runtime_error(strName+" must be hexadecimal string (not '"+strHex+"')");
152 2 : return ParseHex(strHex);
153 330 : }
|