From ae775b5b311982a3d932a9e34ddc94ce597dcaaf Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Mon, 23 Jun 2014 23:10:24 -0400 Subject: Consolidate CTransaction hex encode/decode into core_io.h, core_{read,write}.cpp --- src/core_read.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/core_read.cpp (limited to 'src/core_read.cpp') diff --git a/src/core_read.cpp b/src/core_read.cpp new file mode 100644 index 000000000..937dcd9c1 --- /dev/null +++ b/src/core_read.cpp @@ -0,0 +1,25 @@ + +#include +#include "core_io.h" +#include "core.h" +#include "serialize.h" + +using namespace std; + +bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx) +{ + if (!IsHex(strHexTx)) + return false; + + vector txData(ParseHex(strHexTx)); + CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION); + try { + ssData >> tx; + } + catch (std::exception &e) { + return false; + } + + return true; +} + -- cgit v1.2.3 From b2aeaa79393608132104183eba117fcbf583148e Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Mon, 23 Jun 2014 23:16:33 -0400 Subject: Move ParseScript() helper, becoming accessible outside src/test/ --- src/core_read.cpp | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) (limited to 'src/core_read.cpp') diff --git a/src/core_read.cpp b/src/core_read.cpp index 937dcd9c1..d5d3cca48 100644 --- a/src/core_read.cpp +++ b/src/core_read.cpp @@ -3,8 +3,85 @@ #include "core_io.h" #include "core.h" #include "serialize.h" +#include "script.h" + +#include +#include +#include +#include +#include using namespace std; +using namespace boost; +using namespace boost::algorithm; + +CScript ParseScript(std::string s) +{ + CScript result; + + static map mapOpNames; + + if (mapOpNames.size() == 0) + { + for (int op = 0; op <= OP_NOP10; op++) + { + // Allow OP_RESERVED to get into mapOpNames + if (op < OP_NOP && op != OP_RESERVED) + continue; + + const char* name = GetOpName((opcodetype)op); + if (strcmp(name, "OP_UNKNOWN") == 0) + continue; + string strName(name); + mapOpNames[strName] = (opcodetype)op; + // Convenience: OP_ADD and just ADD are both recognized: + replace_first(strName, "OP_", ""); + mapOpNames[strName] = (opcodetype)op; + } + } + + vector words; + split(words, s, is_any_of(" \t\n"), token_compress_on); + + BOOST_FOREACH(string w, words) + { + if (w.size() == 0) + { + // Empty string, ignore. (boost::split given '' will return one word) + } + else if (all(w, is_digit()) || + (starts_with(w, "-") && all(string(w.begin()+1, w.end()), is_digit()))) + { + // Number + int64_t n = atoi64(w); + result << n; + } + else if (starts_with(w, "0x") && IsHex(string(w.begin()+2, w.end()))) + { + // Raw hex data, inserted NOT pushed onto stack: + std::vector raw = ParseHex(string(w.begin()+2, w.end())); + result.insert(result.end(), raw.begin(), raw.end()); + } + else if (w.size() >= 2 && starts_with(w, "'") && ends_with(w, "'")) + { + // Single-quoted string, pushed as data. NOTE: this is poor-man's + // parsing, spaces/tabs/newlines in single-quoted strings won't work. + std::vector value(w.begin()+1, w.end()-1); + result << value; + } + else if (mapOpNames.count(w)) + { + // opcode, e.g. OP_ADD or ADD: + result << mapOpNames[w]; + } + else + { + throw runtime_error("script parse error"); + } + } + + return result; +} bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx) { -- cgit v1.2.3 From 2a5840096fd3b6235a4ff4b8488f8d4494414765 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Mon, 23 Jun 2014 19:32:54 -0400 Subject: core_read's ParseScript(): minor cleanups - use .empty() rather than .size() == 0 - use a const_iterator rather than BOOST_FOREACH - validate iterators before creating a string from them --- src/core_read.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'src/core_read.cpp') diff --git a/src/core_read.cpp b/src/core_read.cpp index d5d3cca48..1ecd6db32 100644 --- a/src/core_read.cpp +++ b/src/core_read.cpp @@ -21,7 +21,7 @@ CScript ParseScript(std::string s) static map mapOpNames; - if (mapOpNames.size() == 0) + if (mapOpNames.empty()) { for (int op = 0; op <= OP_NOP10; op++) { @@ -43,36 +43,36 @@ CScript ParseScript(std::string s) vector words; split(words, s, is_any_of(" \t\n"), token_compress_on); - BOOST_FOREACH(string w, words) + for (std::vector::const_iterator w = words.begin(); w != words.end(); ++w) { - if (w.size() == 0) + if (w->empty()) { // Empty string, ignore. (boost::split given '' will return one word) } - else if (all(w, is_digit()) || - (starts_with(w, "-") && all(string(w.begin()+1, w.end()), is_digit()))) + else if (all(*w, is_digit()) || + (starts_with(*w, "-") && all(string(w->begin()+1, w->end()), is_digit()))) { // Number - int64_t n = atoi64(w); + int64_t n = atoi64(*w); result << n; } - else if (starts_with(w, "0x") && IsHex(string(w.begin()+2, w.end()))) + else if (starts_with(*w, "0x") && (w->begin()+2 != w->end()) && IsHex(string(w->begin()+2, w->end()))) { // Raw hex data, inserted NOT pushed onto stack: - std::vector raw = ParseHex(string(w.begin()+2, w.end())); + std::vector raw = ParseHex(string(w->begin()+2, w->end())); result.insert(result.end(), raw.begin(), raw.end()); } - else if (w.size() >= 2 && starts_with(w, "'") && ends_with(w, "'")) + else if (w->size() >= 2 && starts_with(*w, "'") && ends_with(*w, "'")) { // Single-quoted string, pushed as data. NOTE: this is poor-man's // parsing, spaces/tabs/newlines in single-quoted strings won't work. - std::vector value(w.begin()+1, w.end()-1); + std::vector value(w->begin()+1, w->end()-1); result << value; } - else if (mapOpNames.count(w)) + else if (mapOpNames.count(*w)) { // opcode, e.g. OP_ADD or ADD: - result << mapOpNames[w]; + result << mapOpNames[*w]; } else { -- cgit v1.2.3 From cbe39a38526a6c17619d02cc697b80ebfd57203b Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 29 Jul 2014 11:12:44 -0400 Subject: Add "bitcoin-tx" command line utility and supporting modules. This is a simple utility that provides command line manipulation of a hex-encoded TX. The utility takes a hex string on the command line as input, performs zero or more mutations, and outputs a hex string to standard output. This utility is also an intentional exercise of the "bitcoin library" concept. It is designed to require minimal libraries, and works entirely without need for any RPC or P2P communication. See "bitcoin-tx --help" for command and options summary. --- src/core_read.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'src/core_read.cpp') diff --git a/src/core_read.cpp b/src/core_read.cpp index 1ecd6db32..0f06bb695 100644 --- a/src/core_read.cpp +++ b/src/core_read.cpp @@ -4,12 +4,14 @@ #include "core.h" #include "serialize.h" #include "script.h" +#include "util.h" #include #include #include #include #include +#include "univalue/univalue.h" using namespace std; using namespace boost; @@ -100,3 +102,26 @@ bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx) return true; } +uint256 ParseHashUV(const UniValue& v, const string& strName) +{ + string strHex; + if (v.isStr()) + strHex = v.getValStr(); + if (!IsHex(strHex)) // Note: IsHex("") is false + throw runtime_error(strName+" must be hexadecimal string (not '"+strHex+"')"); + + uint256 result; + result.SetHex(strHex); + return result; +} + +vector ParseHexUV(const UniValue& v, const string& strName) +{ + string strHex; + if (v.isStr()) + strHex = v.getValStr(); + if (!IsHex(strHex)) + throw runtime_error(strName+" must be hexadecimal string (not '"+strHex+"')"); + return ParseHex(strHex); +} + -- cgit v1.2.3