Bitcoin ABC 0.32.6
P2P Digital Currency
core_read.cpp
Go to the documentation of this file.
1// Copyright (c) 2009-2016 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>
9#include <psbt.h>
10#include <script/script.h>
11#include <script/sign.h>
12#include <serialize.h>
13#include <streams.h>
14#include <util/strencodings.h>
15#include <util/string.h>
16
17#include <univalue.h>
18
19#include <boost/algorithm/string/classification.hpp>
20#include <boost/algorithm/string/split.hpp>
21
22#include <algorithm>
23#include <string>
24
25namespace {
26
27opcodetype ParseOpCode(const std::string &s) {
28 static std::map<std::string, opcodetype> mapOpNames;
29
30 if (mapOpNames.empty()) {
31 for (int op = 0; op < FIRST_UNDEFINED_OP_VALUE; op++) {
32 if (op < OP_PUSHDATA1) {
33 continue;
34 }
35
36 std::string strName = GetOpName(static_cast<opcodetype>(op));
37 if (strName == "OP_UNKNOWN") {
38 continue;
39 }
40
41 mapOpNames[strName] = static_cast<opcodetype>(op);
42 // Convenience: OP_ADD and just ADD are both recognized:
43 // strName starts with "OP_"
44 if (strName.compare(0, 3, "OP_") == 0) {
45 mapOpNames[strName.substr(3)] = static_cast<opcodetype>(op);
46 }
47 }
48 }
49
50 auto it = mapOpNames.find(s);
51 if (it == mapOpNames.end()) {
52 throw std::runtime_error("script parse error: unknown opcode " + s);
53 }
54 return it->second;
55}
56
57} // namespace
58
59CScript ParseScript(const std::string &s) {
60 CScript result;
61
62 std::vector<std::string> words;
63 boost::algorithm::split(words, s, boost::algorithm::is_any_of(" \t\n"),
64 boost::algorithm::token_compress_on);
65
66 size_t push_size = 0, next_push_size = 0;
67 size_t script_size = 0;
68 // Deal with PUSHDATA1 operation with some more hacks.
69 size_t push_data_size = 0;
70
71 for (const auto &w : words) {
72 if (w.empty()) {
73 // Empty string, ignore. (boost::split given '' will return one
74 // word)
75 continue;
76 }
77
78 // Update script size.
79 script_size = result.size();
80
81 // Make sure we keep track of the size of push operations.
82 push_size = next_push_size;
83 next_push_size = 0;
84
85 // Decimal numbers
86 if (std::all_of(w.begin(), w.end(), ::IsDigit) ||
87 (w.front() == '-' && w.size() > 1 &&
88 std::all_of(w.begin() + 1, w.end(), ::IsDigit))) {
89 // Number
90 const auto num{ToIntegral<int64_t>(w)};
91
92 // Limit the range of numbers ParseScript accepts in decimal
93 // since numbers outside -0x7FFFFFFFFFFFFFFF...0x7FFFFFFFFFFFFFFF
94 // are illegal in scripts.
95 // This means, only the int64_t -0x8000000000000000 is illegal.
96 if (!num.has_value() ||
97 num == std::numeric_limits<int64_t>::min()) {
98 throw std::runtime_error(
99 "script parse error: decimal numeric value only allowed in "
100 "the range -0x7FFFFFFFFFFFFFFF...0x7FFFFFFFFFFFFFFF");
101 }
102
103 result << num.value();
104 goto next;
105 }
106
107 // Hex Data
108 if (w.substr(0, 2) == "0x" && w.size() > 2) {
109 if (!IsHex(std::string(w.begin() + 2, w.end()))) {
110 // Should only arrive here for improperly formatted hex values
111 throw std::runtime_error("Hex numbers expected to be formatted "
112 "in full-byte chunks (ex: 0x00 "
113 "instead of 0x0)");
114 }
115
116 // Raw hex data, inserted NOT pushed onto stack:
117 std::vector<uint8_t> raw =
118 ParseHex(std::string(w.begin() + 2, w.end()));
119
120 result.insert(result.end(), raw.begin(), raw.end());
121 goto next;
122 }
123
124 if (w.size() >= 2 && w.front() == '\'' && w.back() == '\'') {
125 // Single-quoted string, pushed as data. NOTE: this is poor-man's
126 // parsing, spaces/tabs/newlines in single-quoted strings won't
127 // work.
128 std::vector<uint8_t> value(w.begin() + 1, w.end() - 1);
129 result << value;
130 goto next;
131 }
132
133 // opcode, e.g. OP_ADD or ADD:
134 result << ParseOpCode(w);
135
136 next:
137 size_t size_change = result.size() - script_size;
138
139 // If push_size is set, ensure have added the right amount of stuff.
140 if (push_size != 0 && size_change != push_size) {
141 throw std::runtime_error(
142 "Wrong number of bytes being pushed. Expected:" +
143 ToString(push_size) + " Pushed:" + ToString(size_change));
144 }
145
146 // If push_size is set, and we have push_data_size set, then we have a
147 // PUSHDATAX opcode. We need to read it's push size as a LE value for
148 // the next iteration of this loop.
149 if (push_size != 0 && push_data_size != 0) {
150 auto offset = &result[script_size];
151
152 // Push data size is not a CScriptNum (Because it is
153 // 2's-complement instead of 1's complement). We need to use
154 // ReadLE(N) instead of converting to a CScriptNum.
155 if (push_data_size == 1) {
156 next_push_size = *offset;
157 } else if (push_data_size == 2) {
158 next_push_size = ReadLE16(offset);
159 } else if (push_data_size == 4) {
160 next_push_size = ReadLE32(offset);
161 }
162
163 push_data_size = 0;
164 }
165
166 // If push_size is unset, but size_change is 1, that means we have an
167 // opcode in the form of `0x00` or <opcodename>. We will check to see
168 // if it is a push operation and set state accordingly
169 if (push_size == 0 && size_change == 1) {
170 opcodetype op = opcodetype(*result.rbegin());
171
172 // If we have what looks like an immediate push, figure out its
173 // size.
174 if (op < OP_PUSHDATA1) {
175 next_push_size = op;
176 continue;
177 }
178
179 switch (op) {
180 case OP_PUSHDATA1:
181 push_data_size = next_push_size = 1;
182 break;
183 case OP_PUSHDATA2:
184 push_data_size = next_push_size = 2;
185 break;
186 case OP_PUSHDATA4:
187 push_data_size = next_push_size = 4;
188 break;
189 default:
190 break;
191 }
192 }
193 }
194
195 return result;
196}
197
198bool DecodeHexTx(CMutableTransaction &tx, const std::string &strHexTx) {
199 if (!IsHex(strHexTx)) {
200 return false;
201 }
202
203 std::vector<uint8_t> txData(ParseHex(strHexTx));
204
205 DataStream ssData{txData};
206 try {
207 ssData >> tx;
208 if (ssData.eof()) {
209 return true;
210 }
211 } catch (const std::exception &e) {
212 // Fall through.
213 }
214
215 return false;
216}
217
218bool DecodeHexBlockHeader(CBlockHeader &header, const std::string &hex_header) {
219 if (!IsHex(hex_header)) {
220 return false;
221 }
222
223 const std::vector<uint8_t> header_data{ParseHex(hex_header)};
224 DataStream ser_header{header_data};
225 try {
226 ser_header >> header;
227 } catch (const std::exception &) {
228 return false;
229 }
230 return true;
231}
232
233bool DecodeHexBlk(CBlock &block, const std::string &strHexBlk) {
234 if (!IsHex(strHexBlk)) {
235 return false;
236 }
237
238 std::vector<uint8_t> blockData(ParseHex(strHexBlk));
239 DataStream ssBlock{blockData};
240 try {
241 ssBlock >> block;
242 } catch (const std::exception &) {
243 return false;
244 }
245
246 return true;
247}
248
249bool ParseHashStr(const std::string &strHex, uint256 &result) {
250 if ((strHex.size() != 64) || !IsHex(strHex)) {
251 return false;
252 }
253
254 result.SetHex(strHex);
255 return true;
256}
257
258std::vector<uint8_t> ParseHexUV(const UniValue &v, const std::string &strName) {
259 std::string strHex;
260 if (v.isStr()) {
261 strHex = v.getValStr();
262 }
263
264 if (!IsHex(strHex)) {
265 throw std::runtime_error(
266 strName + " must be hexadecimal string (not '" + strHex + "')");
267 }
268
269 return ParseHex(strHex);
270}
271
273 SigHashType sigHashType = SigHashType().withForkId();
274 if (!sighash.isNull()) {
275 static std::map<std::string, int> map_sighash_values = {
276 {"ALL", SIGHASH_ALL},
277 {"ALL|ANYONECANPAY", SIGHASH_ALL | SIGHASH_ANYONECANPAY},
278 {"ALL|FORKID", SIGHASH_ALL | SIGHASH_FORKID},
279 {"ALL|FORKID|ANYONECANPAY",
281 {"NONE", SIGHASH_NONE},
282 {"NONE|ANYONECANPAY", SIGHASH_NONE | SIGHASH_ANYONECANPAY},
283 {"NONE|FORKID", SIGHASH_NONE | SIGHASH_FORKID},
284 {"NONE|FORKID|ANYONECANPAY",
286 {"SINGLE", SIGHASH_SINGLE},
287 {"SINGLE|ANYONECANPAY", SIGHASH_SINGLE | SIGHASH_ANYONECANPAY},
288 {"SINGLE|FORKID", SIGHASH_SINGLE | SIGHASH_FORKID},
289 {"SINGLE|FORKID|ANYONECANPAY",
291 };
292 const std::string &strHashType = sighash.get_str();
293 const auto &it = map_sighash_values.find(strHashType);
294 if (it != map_sighash_values.end()) {
295 sigHashType = SigHashType(it->second);
296 } else {
297 throw std::runtime_error(strHashType +
298 " is not a valid sighash parameter.");
299 }
300 }
301 return sigHashType;
302}
Nodes collect new transactions into a block, hash them into a hash tree, and scan through nonce value...
Definition: block.h:23
Definition: block.h:60
A mutable version of CTransaction.
Definition: transaction.h:274
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:118
Signature hash type wrapper class.
Definition: sighashtype.h:37
SigHashType withForkId(bool forkId=true) const
Definition: sighashtype.h:54
const std::string & get_str() const
bool isNull() const
Definition: univalue.h:104
const std::string & getValStr() const
Definition: univalue.h:89
bool isStr() const
Definition: univalue.h:108
void SetHex(const char *psz)
Definition: uint256.cpp:24
256-bit opaque blob.
Definition: uint256.h:129
CScript ParseScript(const std::string &s)
Definition: core_read.cpp:59
bool DecodeHexBlockHeader(CBlockHeader &header, const std::string &hex_header)
Definition: core_read.cpp:218
bool DecodeHexTx(CMutableTransaction &tx, const std::string &strHexTx)
Definition: core_read.cpp:198
std::vector< uint8_t > ParseHexUV(const UniValue &v, const std::string &strName)
Definition: core_read.cpp:258
bool ParseHashStr(const std::string &strHex, uint256 &result)
Parse a hex string into 256 bits.
Definition: core_read.cpp:249
SigHashType ParseSighashString(const UniValue &sighash)
Definition: core_read.cpp:272
bool DecodeHexBlk(CBlock &block, const std::string &strHexBlk)
Definition: core_read.cpp:233
static uint16_t ReadLE16(const uint8_t *ptr)
Definition: common.h:13
static uint32_t ReadLE32(const uint8_t *ptr)
Definition: common.h:19
std::string GetOpName(opcodetype opcode)
Definition: script.cpp:14
opcodetype
Script opcodes.
Definition: script.h:51
@ OP_PUSHDATA4
Definition: script.h:57
@ FIRST_UNDEFINED_OP_VALUE
Definition: script.h:194
@ OP_PUSHDATA1
Definition: script.h:55
@ OP_PUSHDATA2
Definition: script.h:56
@ SIGHASH_FORKID
Definition: sighashtype.h:18
@ SIGHASH_ANYONECANPAY
Definition: sighashtype.h:19
@ SIGHASH_ALL
Definition: sighashtype.h:15
@ SIGHASH_NONE
Definition: sighashtype.h:16
@ SIGHASH_SINGLE
Definition: sighashtype.h:17
constexpr bool IsDigit(char c)
Tests if the given character is a decimal digit.
Definition: strencodings.h:123
std::string ToString(const T &t)
Locale-independent version of std::to_string.
Definition: string.h:108
template std::vector< std::byte > ParseHex(std::string_view)
bool IsHex(std::string_view str)
Returns true if each character in str is a hex character, and has an even number of hex digits.