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