20#include <boost/algorithm/string/classification.hpp>
21#include <boost/algorithm/string/split.hpp>
29 static std::map<std::string, opcodetype> mapOpNames;
31 if (mapOpNames.empty()) {
38 if (strName ==
"OP_UNKNOWN") {
42 mapOpNames[strName] =
static_cast<opcodetype>(op);
45 if (strName.compare(0, 3,
"OP_") == 0) {
46 mapOpNames[strName.substr(3)] =
static_cast<opcodetype>(op);
51 auto it = mapOpNames.find(s);
52 if (it == mapOpNames.end()) {
53 throw std::runtime_error(
"script parse error: unknown opcode " + s);
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);
67 size_t push_size = 0, next_push_size = 0;
68 size_t script_size = 0;
70 size_t push_data_size = 0;
72 for (
const auto &w : words) {
80 script_size = result.size();
83 push_size = next_push_size;
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))) {
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");
107 if (w.substr(0, 2) ==
"0x" && w.size() > 2) {
108 if (!
IsHex(std::string(w.begin() + 2, w.end()))) {
110 throw std::runtime_error(
"Hex numbers expected to be formatted "
111 "in full-byte chunks (ex: 0x00 "
116 std::vector<uint8_t> raw =
117 ParseHex(std::string(w.begin() + 2, w.end()));
119 result.insert(result.end(), raw.begin(), raw.end());
123 if (w.size() >= 2 && w.front() ==
'\'' && w.back() ==
'\'') {
127 std::vector<uint8_t> value(w.begin() + 1, w.end() - 1);
133 result << ParseOpCode(w);
136 size_t size_change = result.size() - script_size;
139 if (push_size != 0 && size_change != push_size) {
140 throw std::runtime_error(
141 "Wrong number of bytes being pushed. Expected:" +
148 if (push_size != 0 && push_data_size != 0) {
149 auto offset = &result[script_size];
154 if (push_data_size == 1) {
155 next_push_size = *offset;
156 }
else if (push_data_size == 2) {
158 }
else if (push_data_size == 4) {
168 if (push_size == 0 && size_change == 1) {
180 push_data_size = next_push_size = 1;
183 push_data_size = next_push_size = 2;
186 push_data_size = next_push_size = 4;
198 if (!
IsHex(strHexTx)) {
202 std::vector<uint8_t> txData(
ParseHex(strHexTx));
210 }
catch (
const std::exception &e) {
218 if (!
IsHex(hex_header)) {
222 const std::vector<uint8_t> header_data{
ParseHex(hex_header)};
225 ser_header >> header;
226 }
catch (
const std::exception &) {
233 if (!
IsHex(strHexBlk)) {
237 std::vector<uint8_t> blockData(
ParseHex(strHexBlk));
241 }
catch (
const std::exception &) {
249 if ((strHex.size() != 64) || !
IsHex(strHex)) {
263 if (!
IsHex(strHex)) {
264 throw std::runtime_error(
265 strName +
" must be hexadecimal string (not '" + strHex +
"')");
274 static std::map<std::string, int> map_sighash_values = {
278 {
"ALL|FORKID|ANYONECANPAY",
283 {
"NONE|FORKID|ANYONECANPAY",
288 {
"SINGLE|FORKID|ANYONECANPAY",
291 std::string strHashType = sighash.
get_str();
292 const auto &it = map_sighash_values.find(strHashType);
293 if (it != map_sighash_values.end()) {
296 throw std::runtime_error(strHashType +
297 " is not a valid sighash parameter.");
Double ended buffer combining vector and stream-like interfaces.
A mutable version of CTransaction.
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.
int64_t atoi64(const std::string &str)
static const int PROTOCOL_VERSION
network protocol versioning