Bitcoin ABC  0.26.3
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 
26 namespace {
27 
28 opcodetype 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 
60 CScript 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  int64_t n = atoi64(w);
92 
93  // limit the range of numbers ParseScript accepts in decimal
94  // since numbers outside -0xFFFFFFFF...0xFFFFFFFF are illegal in
95  // scripts
96  if (n > int64_t{0xffffffff} || n < -1 * int64_t{0xffffffff}) {
97  throw std::runtime_error("script parse error: decimal numeric "
98  "value only allowed in the "
99  "range -0xFFFFFFFF...0xFFFFFFFF");
100  }
101 
102  result << n;
103  goto next;
104  }
105 
106  // Hex Data
107  if (w.substr(0, 2) == "0x" && w.size() > 2) {
108  if (!IsHex(std::string(w.begin() + 2, w.end()))) {
109  // Should only arrive here for improperly formatted hex values
110  throw std::runtime_error("Hex numbers expected to be formatted "
111  "in full-byte chunks (ex: 0x00 "
112  "instead of 0x0)");
113  }
114 
115  // Raw hex data, inserted NOT pushed onto stack:
116  std::vector<uint8_t> raw =
117  ParseHex(std::string(w.begin() + 2, w.end()));
118 
119  result.insert(result.end(), raw.begin(), raw.end());
120  goto next;
121  }
122 
123  if (w.size() >= 2 && w.front() == '\'' && w.back() == '\'') {
124  // Single-quoted string, pushed as data. NOTE: this is poor-man's
125  // parsing, spaces/tabs/newlines in single-quoted strings won't
126  // work.
127  std::vector<uint8_t> value(w.begin() + 1, w.end() - 1);
128  result << value;
129  goto next;
130  }
131 
132  // opcode, e.g. OP_ADD or ADD:
133  result << ParseOpCode(w);
134 
135  next:
136  size_t size_change = result.size() - script_size;
137 
138  // If push_size is set, ensure have added the right amount of stuff.
139  if (push_size != 0 && size_change != push_size) {
140  throw std::runtime_error(
141  "Wrong number of bytes being pushed. Expected:" +
142  ToString(push_size) + " Pushed:" + ToString(size_change));
143  }
144 
145  // If push_size is set, and we have push_data_size set, then we have a
146  // PUSHDATAX opcode. We need to read it's push size as a LE value for
147  // the next iteration of this loop.
148  if (push_size != 0 && push_data_size != 0) {
149  auto offset = &result[script_size];
150 
151  // Push data size is not a CScriptNum (Because it is
152  // 2's-complement instead of 1's complement). We need to use
153  // ReadLE(N) instead of converting to a CScriptNum.
154  if (push_data_size == 1) {
155  next_push_size = *offset;
156  } else if (push_data_size == 2) {
157  next_push_size = ReadLE16(offset);
158  } else if (push_data_size == 4) {
159  next_push_size = ReadLE32(offset);
160  }
161 
162  push_data_size = 0;
163  }
164 
165  // If push_size is unset, but size_change is 1, that means we have an
166  // opcode in the form of `0x00` or <opcodename>. We will check to see
167  // if it is a push operation and set state accordingly
168  if (push_size == 0 && size_change == 1) {
169  opcodetype op = opcodetype(*result.rbegin());
170 
171  // If we have what looks like an immediate push, figure out its
172  // size.
173  if (op < OP_PUSHDATA1) {
174  next_push_size = op;
175  continue;
176  }
177 
178  switch (op) {
179  case OP_PUSHDATA1:
180  push_data_size = next_push_size = 1;
181  break;
182  case OP_PUSHDATA2:
183  push_data_size = next_push_size = 2;
184  break;
185  case OP_PUSHDATA4:
186  push_data_size = next_push_size = 4;
187  break;
188  default:
189  break;
190  }
191  }
192  }
193 
194  return result;
195 }
196 
197 bool DecodeHexTx(CMutableTransaction &tx, const std::string &strHexTx) {
198  if (!IsHex(strHexTx)) {
199  return false;
200  }
201 
202  std::vector<uint8_t> txData(ParseHex(strHexTx));
203 
204  CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
205  try {
206  ssData >> tx;
207  if (ssData.eof()) {
208  return true;
209  }
210  } catch (const std::exception &e) {
211  // Fall through.
212  }
213 
214  return false;
215 }
216 
217 bool DecodeHexBlockHeader(CBlockHeader &header, const std::string &hex_header) {
218  if (!IsHex(hex_header)) {
219  return false;
220  }
221 
222  const std::vector<uint8_t> header_data{ParseHex(hex_header)};
223  CDataStream ser_header(header_data, SER_NETWORK, PROTOCOL_VERSION);
224  try {
225  ser_header >> header;
226  } catch (const std::exception &) {
227  return false;
228  }
229  return true;
230 }
231 
232 bool DecodeHexBlk(CBlock &block, const std::string &strHexBlk) {
233  if (!IsHex(strHexBlk)) {
234  return false;
235  }
236 
237  std::vector<uint8_t> blockData(ParseHex(strHexBlk));
238  CDataStream ssBlock(blockData, SER_NETWORK, PROTOCOL_VERSION);
239  try {
240  ssBlock >> block;
241  } catch (const std::exception &) {
242  return false;
243  }
244 
245  return true;
246 }
247 
248 bool ParseHashStr(const std::string &strHex, uint256 &result) {
249  if ((strHex.size() != 64) || !IsHex(strHex)) {
250  return false;
251  }
252 
253  result.SetHex(strHex);
254  return true;
255 }
256 
257 std::vector<uint8_t> ParseHexUV(const UniValue &v, const std::string &strName) {
258  std::string strHex;
259  if (v.isStr()) {
260  strHex = v.getValStr();
261  }
262 
263  if (!IsHex(strHex)) {
264  throw std::runtime_error(
265  strName + " must be hexadecimal string (not '" + strHex + "')");
266  }
267 
268  return ParseHex(strHex);
269 }
270 
272  SigHashType sigHashType = SigHashType().withForkId();
273  if (!sighash.isNull()) {
274  static std::map<std::string, int> map_sighash_values = {
275  {"ALL", SIGHASH_ALL},
276  {"ALL|ANYONECANPAY", SIGHASH_ALL | SIGHASH_ANYONECANPAY},
277  {"ALL|FORKID", SIGHASH_ALL | SIGHASH_FORKID},
278  {"ALL|FORKID|ANYONECANPAY",
280  {"NONE", SIGHASH_NONE},
281  {"NONE|ANYONECANPAY", SIGHASH_NONE | SIGHASH_ANYONECANPAY},
282  {"NONE|FORKID", SIGHASH_NONE | SIGHASH_FORKID},
283  {"NONE|FORKID|ANYONECANPAY",
285  {"SINGLE", SIGHASH_SINGLE},
286  {"SINGLE|ANYONECANPAY", SIGHASH_SINGLE | SIGHASH_ANYONECANPAY},
287  {"SINGLE|FORKID", SIGHASH_SINGLE | SIGHASH_FORKID},
288  {"SINGLE|FORKID|ANYONECANPAY",
290  };
291  std::string strHashType = sighash.get_str();
292  const auto &it = map_sighash_values.find(strHashType);
293  if (it != map_sighash_values.end()) {
294  sigHashType = SigHashType(it->second);
295  } else {
296  throw std::runtime_error(strHashType +
297  " is not a valid sighash parameter.");
298  }
299  }
300  return sigHashType;
301 }
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
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:199
bool eof() const
Definition: streams.h:349
A mutable version of CTransaction.
Definition: transaction.h:274
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:431
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:89
const std::string & getValStr() const
Definition: univalue.h:77
bool isStr() const
Definition: univalue.h:93
void SetHex(const char *psz)
Definition: uint256.cpp:24
size_type size() const
Definition: prevector.h:386
iterator end()
Definition: prevector.h:392
iterator insert(iterator pos, const T &value)
Definition: prevector.h:443
reverse_iterator rbegin()
Definition: prevector.h:395
256-bit opaque blob.
Definition: uint256.h:127
CScript ParseScript(const std::string &s)
Definition: core_read.cpp:60
std::vector< uint8_t > ParseHexUV(const UniValue &v, const std::string &strName)
Definition: core_read.cpp:257
bool DecodeHexBlockHeader(CBlockHeader &header, const std::string &hex_header)
Definition: core_read.cpp:217
bool DecodeHexTx(CMutableTransaction &tx, const std::string &strHexTx)
Definition: core_read.cpp:197
bool ParseHashStr(const std::string &strHex, uint256 &result)
Parse a hex string into 256 bits.
Definition: core_read.cpp:248
SigHashType ParseSighashString(const UniValue &sighash)
Definition: core_read.cpp:271
bool DecodeHexBlk(CBlock &block, const std::string &strHexBlk)
Definition: core_read.cpp:232
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:47
@ OP_PUSHDATA4
Definition: script.h:53
@ FIRST_UNDEFINED_OP_VALUE
Definition: script.h:190
@ OP_PUSHDATA1
Definition: script.h:51
@ OP_PUSHDATA2
Definition: script.h:52
@ SER_NETWORK
Definition: serialize.h:166
@ 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
bool IsHex(const std::string &str)
Returns true if each character in str is a hex character, and has an even number of hex digits.
int64_t atoi64(const std::string &str)
std::vector< uint8_t > ParseHex(const char *psz)
constexpr bool IsDigit(char c)
Tests if the given character is a decimal digit.
Definition: strencodings.h:83
std::string ToString(const T &t)
Locale-independent version of std::to_string.
Definition: string.h:87
static const int PROTOCOL_VERSION
network protocol versioning
Definition: version.h:11