19#include <boost/algorithm/string/classification.hpp>
20#include <boost/algorithm/string/split.hpp>
28 static std::map<std::string, opcodetype> mapOpNames;
30 if (mapOpNames.empty()) {
37 if (strName ==
"OP_UNKNOWN") {
41 mapOpNames[strName] =
static_cast<opcodetype>(op);
44 if (strName.compare(0, 3,
"OP_") == 0) {
45 mapOpNames[strName.substr(3)] =
static_cast<opcodetype>(op);
50 auto it = mapOpNames.find(s);
51 if (it == mapOpNames.end()) {
52 throw std::runtime_error(
"script parse error: unknown opcode " + s);
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);
66 size_t push_size = 0, next_push_size = 0;
67 size_t script_size = 0;
69 size_t push_data_size = 0;
71 for (
const auto &w : words) {
79 script_size = result.size();
82 push_size = next_push_size;
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))) {
90 const auto num{ToIntegral<int64_t>(w)};
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");
103 result << num.value();
108 if (w.substr(0, 2) ==
"0x" && w.size() > 2) {
109 if (!
IsHex(std::string(w.begin() + 2, w.end()))) {
111 throw std::runtime_error(
"Hex numbers expected to be formatted "
112 "in full-byte chunks (ex: 0x00 "
117 std::vector<uint8_t> raw =
118 ParseHex(std::string(w.begin() + 2, w.end()));
120 result.insert(result.end(), raw.begin(), raw.end());
124 if (w.size() >= 2 && w.front() ==
'\'' && w.back() ==
'\'') {
128 std::vector<uint8_t> value(w.begin() + 1, w.end() - 1);
134 result << ParseOpCode(w);
137 size_t size_change = result.size() - script_size;
140 if (push_size != 0 && size_change != push_size) {
141 throw std::runtime_error(
142 "Wrong number of bytes being pushed. Expected:" +
149 if (push_size != 0 && push_data_size != 0) {
150 auto offset = &result[script_size];
155 if (push_data_size == 1) {
156 next_push_size = *offset;
157 }
else if (push_data_size == 2) {
159 }
else if (push_data_size == 4) {
169 if (push_size == 0 && size_change == 1) {
181 push_data_size = next_push_size = 1;
184 push_data_size = next_push_size = 2;
187 push_data_size = next_push_size = 4;
199 if (!
IsHex(strHexTx)) {
203 std::vector<uint8_t> txData(
ParseHex(strHexTx));
211 }
catch (
const std::exception &e) {
219 if (!
IsHex(hex_header)) {
223 const std::vector<uint8_t> header_data{
ParseHex(hex_header)};
226 ser_header >> header;
227 }
catch (
const std::exception &) {
234 if (!
IsHex(strHexBlk)) {
238 std::vector<uint8_t> blockData(
ParseHex(strHexBlk));
242 }
catch (
const std::exception &) {
250 if ((strHex.size() != 64) || !
IsHex(strHex)) {
264 if (!
IsHex(strHex)) {
265 throw std::runtime_error(
266 strName +
" must be hexadecimal string (not '" + strHex +
"')");
275 static std::map<std::string, int> map_sighash_values = {
279 {
"ALL|FORKID|ANYONECANPAY",
284 {
"NONE|FORKID|ANYONECANPAY",
289 {
"SINGLE|FORKID|ANYONECANPAY",
292 const std::string &strHashType = sighash.
get_str();
293 const auto &it = map_sighash_values.find(strHashType);
294 if (it != map_sighash_values.end()) {
297 throw std::runtime_error(strHashType +
298 " is not a valid sighash parameter.");
A mutable version of CTransaction.
Double ended buffer combining vector and stream-like interfaces.
Signature hash type wrapper class.
SigHashType withForkId(bool forkId=true) const
const std::string & get_str() const
const std::string & getValStr() const
void SetHex(const char *psz)
CScript ParseScript(const std::string &s)
bool DecodeHexBlockHeader(CBlockHeader &header, const std::string &hex_header)
bool DecodeHexTx(CMutableTransaction &tx, const std::string &strHexTx)
std::vector< uint8_t > ParseHexUV(const UniValue &v, const std::string &strName)
bool ParseHashStr(const std::string &strHex, uint256 &result)
Parse a hex string into 256 bits.
SigHashType ParseSighashString(const UniValue &sighash)
bool DecodeHexBlk(CBlock &block, const std::string &strHexBlk)
static uint16_t ReadLE16(const uint8_t *ptr)
static uint32_t ReadLE32(const uint8_t *ptr)
std::string GetOpName(opcodetype opcode)
opcodetype
Script opcodes.
@ FIRST_UNDEFINED_OP_VALUE
constexpr bool IsDigit(char c)
Tests if the given character is a decimal digit.
std::string ToString(const T &t)
Locale-independent version of std::to_string.
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.