Changeset View
Changeset View
Standalone View
Standalone View
src/core_read.cpp
Show First 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | if (mapOpNames.empty()) { | ||||
mapOpNames[strName] = (opcodetype)op; | mapOpNames[strName] = (opcodetype)op; | ||||
} | } | ||||
} | } | ||||
std::vector<std::string> words; | std::vector<std::string> words; | ||||
boost::algorithm::split(words, s, boost::algorithm::is_any_of(" \t\n"), | boost::algorithm::split(words, s, boost::algorithm::is_any_of(" \t\n"), | ||||
boost::algorithm::token_compress_on); | boost::algorithm::token_compress_on); | ||||
size_t push_size = 0, next_push_size = 0; | |||||
size_t script_size = 0; | |||||
for (const auto &w : words) { | for (const auto &w : words) { | ||||
if (w.empty()) { | if (w.empty()) { | ||||
// Empty string, ignore. (boost::split given '' will return one | // Empty string, ignore. (boost::split given '' will return one | ||||
// word) | // word) | ||||
continue; | continue; | ||||
} | } | ||||
// Check that the expected number of byte where pushed. | |||||
if (push_size && (result.size() - script_size) != push_size) { | |||||
throw std::runtime_error( | |||||
"Hex number doesn't match the number of bytes being pushed"); | |||||
} | |||||
// Update script size. | |||||
script_size = result.size(); | |||||
// Make sure we keep track of the size of push operations. | |||||
push_size = next_push_size; | |||||
next_push_size = 0; | |||||
if (all(w, boost::algorithm::is_digit()) || | if (all(w, boost::algorithm::is_digit()) || | ||||
(boost::algorithm::starts_with(w, "-") && | (boost::algorithm::starts_with(w, "-") && | ||||
all(std::string(w.begin() + 1, w.end()), | all(std::string(w.begin() + 1, w.end()), | ||||
boost::algorithm::is_digit()))) { | boost::algorithm::is_digit()))) { | ||||
// Number | // Number | ||||
int64_t n = atoi64(w); | int64_t n = atoi64(w); | ||||
result << n; | result << n; | ||||
continue; | continue; | ||||
} | } | ||||
if (boost::algorithm::starts_with(w, "0x") && | if (boost::algorithm::starts_with(w, "0x") && | ||||
(w.begin() + 2 != w.end())) { | (w.begin() + 2 != w.end())) { | ||||
if (!IsHex(std::string(w.begin() + 2, w.end()))) { | if (!IsHex(std::string(w.begin() + 2, w.end()))) { | ||||
// Should only arrive here for improperly formatted hex values | // Should only arrive here for improperly formatted hex values | ||||
throw std::runtime_error("Hex numbers expected to be formatted " | throw std::runtime_error("Hex numbers expected to be formatted " | ||||
"in full-byte chunks (ex: 0x00 " | "in full-byte chunks (ex: 0x00 " | ||||
"instead of 0x0)"); | "instead of 0x0)"); | ||||
} | } | ||||
// Raw hex data, inserted NOT pushed onto stack: | // Raw hex data, inserted NOT pushed onto stack: | ||||
std::vector<uint8_t> raw = | std::vector<uint8_t> raw = | ||||
ParseHex(std::string(w.begin() + 2, w.end())); | ParseHex(std::string(w.begin() + 2, w.end())); | ||||
if (push_size && raw.size() != push_size) { | |||||
throw std::runtime_error("Hex number doesn't match the " | |||||
"number of bytes being pushed"); | |||||
} | |||||
// If we have what looks like an immediate push, figure out its | |||||
// size. | |||||
if (!push_size && raw.size() == 1 && raw[0] < OP_PUSHDATA1) { | |||||
next_push_size = raw[0]; | |||||
} | |||||
result.insert(result.end(), raw.begin(), raw.end()); | result.insert(result.end(), raw.begin(), raw.end()); | ||||
continue; | continue; | ||||
} | } | ||||
if (w.size() >= 2 && boost::algorithm::starts_with(w, "'") && | if (w.size() >= 2 && boost::algorithm::starts_with(w, "'") && | ||||
boost::algorithm::ends_with(w, "'")) { | boost::algorithm::ends_with(w, "'")) { | ||||
// Single-quoted string, pushed as data. NOTE: this is poor-man's | // Single-quoted string, pushed as data. NOTE: this is poor-man's | ||||
// parsing, spaces/tabs/newlines in single-quoted strings won't | // parsing, spaces/tabs/newlines in single-quoted strings won't | ||||
// work. | // work. | ||||
std::vector<uint8_t> value(w.begin() + 1, w.end() - 1); | std::vector<uint8_t> value(w.begin() + 1, w.end() - 1); | ||||
result << value; | result << value; | ||||
continue; | continue; | ||||
} | } | ||||
if (mapOpNames.count(w)) { | if (mapOpNames.count(w)) { | ||||
// opcode, e.g. OP_ADD or ADD: | // opcode, e.g. OP_ADD or ADD: | ||||
result << mapOpNames[w]; | opcodetype op = mapOpNames[w]; | ||||
switch (op) { | |||||
case OP_PUSHDATA1: | |||||
next_push_size = 1; | |||||
break; | |||||
case OP_PUSHDATA2: | |||||
next_push_size = 2; | |||||
break; | |||||
case OP_PUSHDATA4: | |||||
next_push_size = 4; | |||||
break; | |||||
default: | |||||
break; | |||||
} | |||||
result << op; | |||||
continue; | continue; | ||||
} | } | ||||
throw std::runtime_error("Error parsing script: " + s); | throw std::runtime_error("Error parsing script: " + s); | ||||
} | } | ||||
// Check that the expected number of byte where pushed. | |||||
if (push_size && (result.size() - script_size) != push_size) { | |||||
throw std::runtime_error( | |||||
"Hex number doesn't match the number of bytes being pushed"); | |||||
} | |||||
return result; | return result; | ||||
} | } | ||||
bool DecodeHexTx(CMutableTransaction &tx, const std::string &strHexTx) { | bool DecodeHexTx(CMutableTransaction &tx, const std::string &strHexTx) { | ||||
if (!IsHex(strHexTx)) { | if (!IsHex(strHexTx)) { | ||||
return false; | return false; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 66 Lines • Show Last 20 Lines |