2017-11-09 19:34:51 +01:00
|
|
|
/*
|
|
|
|
|
* This file is part of the Flowee project
|
|
|
|
|
* Copyright (c) 2009-2015 The Bitcoin Core developers
|
|
|
|
|
*
|
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
|
|
|
|
|
2014-06-23 23:10:24 -04:00
|
|
|
|
|
|
|
|
#include "core_io.h"
|
2014-09-14 12:43:56 +02:00
|
|
|
|
2021-11-02 10:08:27 +01:00
|
|
|
#include "primitives/MutableBlock.h"
|
2014-11-18 21:03:02 +00:00
|
|
|
#include "primitives/transaction.h"
|
2019-03-11 14:47:12 +01:00
|
|
|
#include "primitives/script.h"
|
2014-09-14 12:43:56 +02:00
|
|
|
#include "serialize.h"
|
2019-03-11 14:47:12 +01:00
|
|
|
#include "streaming/streams.h"
|
2015-09-04 16:11:34 +02:00
|
|
|
#include <univalue.h>
|
2014-09-24 23:32:36 -04:00
|
|
|
#include "utilstrencodings.h"
|
2022-07-06 22:50:53 +02:00
|
|
|
#include <BitcoinVersion.h>
|
2014-06-23 23:16:33 -04:00
|
|
|
|
|
|
|
|
#include <boost/algorithm/string/classification.hpp>
|
|
|
|
|
#include <boost/algorithm/string/predicate.hpp>
|
|
|
|
|
#include <boost/algorithm/string/replace.hpp>
|
2014-09-14 12:43:56 +02:00
|
|
|
#include <boost/algorithm/string/split.hpp>
|
2014-06-23 23:10:24 -04:00
|
|
|
|
2015-05-31 15:36:44 +02:00
|
|
|
CScript ParseScript(const std::string& s)
|
2014-06-23 23:16:33 -04:00
|
|
|
{
|
|
|
|
|
CScript result;
|
|
|
|
|
|
2017-06-21 00:41:45 -04:00
|
|
|
static std::map<std::string, opcodetype> mapOpNames;
|
2014-06-23 23:16:33 -04:00
|
|
|
|
2014-06-23 19:32:54 -04:00
|
|
|
if (mapOpNames.empty())
|
2014-06-23 23:16:33 -04:00
|
|
|
{
|
|
|
|
|
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;
|
2017-06-21 00:16:55 -04:00
|
|
|
std::string strName(name);
|
2014-06-23 23:16:33 -04:00
|
|
|
mapOpNames[strName] = (opcodetype)op;
|
|
|
|
|
// Convenience: OP_ADD and just ADD are both recognized:
|
2014-12-19 16:50:15 -05:00
|
|
|
boost::algorithm::replace_first(strName, "OP_", "");
|
2014-06-23 23:16:33 -04:00
|
|
|
mapOpNames[strName] = (opcodetype)op;
|
|
|
|
|
}
|
2026-05-14 15:01:57 +02:00
|
|
|
const auto addAlias = [&](const char *name, opcodetype op) {
|
|
|
|
|
mapOpNames[name] = op;
|
|
|
|
|
std::string shortName(name);
|
|
|
|
|
boost::algorithm::replace_first(shortName, "OP_", "");
|
|
|
|
|
mapOpNames[shortName] = op;
|
|
|
|
|
};
|
|
|
|
|
addAlias("OP_VERIF", OP_VERIF);
|
|
|
|
|
addAlias("OP_VERNOTIF", OP_VERNOTIF);
|
|
|
|
|
addAlias("OP_RESERVED1", OP_RESERVED1);
|
|
|
|
|
addAlias("OP_RESERVED2", OP_RESERVED2);
|
|
|
|
|
addAlias("OP_2MUL", OP_2MUL);
|
|
|
|
|
addAlias("OP_2DIV", OP_2DIV);
|
|
|
|
|
addAlias("OP_LSHIFT", OP_LSHIFT);
|
|
|
|
|
addAlias("OP_RSHIFT", OP_RSHIFT);
|
2014-06-23 23:16:33 -04:00
|
|
|
}
|
|
|
|
|
|
2017-06-21 00:19:39 -04:00
|
|
|
std::vector<std::string> words;
|
2014-12-19 16:50:15 -05:00
|
|
|
boost::algorithm::split(words, s, boost::algorithm::is_any_of(" \t\n"), boost::algorithm::token_compress_on);
|
2014-06-23 23:16:33 -04:00
|
|
|
|
2014-06-23 19:32:54 -04:00
|
|
|
for (std::vector<std::string>::const_iterator w = words.begin(); w != words.end(); ++w)
|
2014-06-23 23:16:33 -04:00
|
|
|
{
|
2014-06-23 19:32:54 -04:00
|
|
|
if (w->empty())
|
2014-06-23 23:16:33 -04:00
|
|
|
{
|
|
|
|
|
// Empty string, ignore. (boost::split given '' will return one word)
|
|
|
|
|
}
|
2014-12-19 16:50:15 -05:00
|
|
|
else if (all(*w, boost::algorithm::is_digit()) ||
|
2017-06-21 00:45:05 -04:00
|
|
|
(boost::algorithm::starts_with(*w, "-") && all(std::string(w->begin()+1, w->end()), boost::algorithm::is_digit())))
|
2014-06-23 23:16:33 -04:00
|
|
|
{
|
|
|
|
|
// Number
|
2014-06-23 19:32:54 -04:00
|
|
|
int64_t n = atoi64(*w);
|
2014-06-23 23:16:33 -04:00
|
|
|
result << n;
|
|
|
|
|
}
|
2017-06-21 00:45:05 -04:00
|
|
|
else if (boost::algorithm::starts_with(*w, "0x") && (w->begin()+2 != w->end()) && IsHex(std::string(w->begin()+2, w->end())))
|
2014-06-23 23:16:33 -04:00
|
|
|
{
|
|
|
|
|
// Raw hex data, inserted NOT pushed onto stack:
|
2017-06-21 00:45:05 -04:00
|
|
|
std::vector<unsigned char> raw = ParseHex(std::string(w->begin()+2, w->end()));
|
2014-06-23 23:16:33 -04:00
|
|
|
result.insert(result.end(), raw.begin(), raw.end());
|
|
|
|
|
}
|
2014-12-19 16:50:15 -05:00
|
|
|
else if (w->size() >= 2 && boost::algorithm::starts_with(*w, "'") && boost::algorithm::ends_with(*w, "'"))
|
2014-06-23 23:16:33 -04:00
|
|
|
{
|
|
|
|
|
// Single-quoted string, pushed as data. NOTE: this is poor-man's
|
|
|
|
|
// parsing, spaces/tabs/newlines in single-quoted strings won't work.
|
2014-06-23 19:32:54 -04:00
|
|
|
std::vector<unsigned char> value(w->begin()+1, w->end()-1);
|
2014-06-23 23:16:33 -04:00
|
|
|
result << value;
|
|
|
|
|
}
|
2014-06-23 19:32:54 -04:00
|
|
|
else if (mapOpNames.count(*w))
|
2014-06-23 23:16:33 -04:00
|
|
|
{
|
|
|
|
|
// opcode, e.g. OP_ADD or ADD:
|
2014-06-23 19:32:54 -04:00
|
|
|
result << mapOpNames[*w];
|
2014-06-23 23:16:33 -04:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2017-06-21 00:39:47 -04:00
|
|
|
throw std::runtime_error("script parse error");
|
2014-06-23 23:16:33 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
2014-06-23 23:10:24 -04:00
|
|
|
|
|
|
|
|
bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx)
|
|
|
|
|
{
|
|
|
|
|
if (!IsHex(strHexTx))
|
|
|
|
|
return false;
|
|
|
|
|
|
2017-06-21 00:19:39 -04:00
|
|
|
std::vector<unsigned char> txData(ParseHex(strHexTx));
|
2014-06-23 23:10:24 -04:00
|
|
|
CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
|
|
|
|
|
try {
|
|
|
|
|
ssData >> tx;
|
|
|
|
|
}
|
2014-12-07 13:29:06 +01:00
|
|
|
catch (const std::exception&) {
|
2014-06-23 23:10:24 -04:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-02 09:36:09 +01:00
|
|
|
bool DecodeHexBlk(MutableBlock& block, const std::string& strHexBlk)
|
2014-10-30 02:56:33 +00:00
|
|
|
{
|
|
|
|
|
if (!IsHex(strHexBlk))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
std::vector<unsigned char> blockData(ParseHex(strHexBlk));
|
|
|
|
|
CDataStream ssBlock(blockData, SER_NETWORK, PROTOCOL_VERSION);
|
|
|
|
|
try {
|
|
|
|
|
ssBlock >> block;
|
|
|
|
|
}
|
2014-12-07 13:29:06 +01:00
|
|
|
catch (const std::exception&) {
|
2014-10-30 02:56:33 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-21 00:16:55 -04:00
|
|
|
uint256 ParseHashUV(const UniValue& v, const std::string& strName)
|
2014-07-29 11:12:44 -04:00
|
|
|
{
|
2017-06-21 00:16:55 -04:00
|
|
|
std::string strHex;
|
2014-07-29 11:12:44 -04:00
|
|
|
if (v.isStr())
|
|
|
|
|
strHex = v.getValStr();
|
2014-12-17 09:34:09 +00:00
|
|
|
return ParseHashStr(strHex, strName); // Note: ParseHashStr("") throws a runtime_error
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint256 ParseHashStr(const std::string& strHex, const std::string& strName)
|
|
|
|
|
{
|
2014-07-29 11:12:44 -04:00
|
|
|
if (!IsHex(strHex)) // Note: IsHex("") is false
|
2017-06-21 00:39:47 -04:00
|
|
|
throw std::runtime_error(strName+" must be hexadecimal string (not '"+strHex+"')");
|
2014-07-29 11:12:44 -04:00
|
|
|
|
|
|
|
|
uint256 result;
|
|
|
|
|
result.SetHex(strHex);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-21 00:19:39 -04:00
|
|
|
std::vector<unsigned char> ParseHexUV(const UniValue& v, const std::string& strName)
|
2014-07-29 11:12:44 -04:00
|
|
|
{
|
2017-06-21 00:16:55 -04:00
|
|
|
std::string strHex;
|
2014-07-29 11:12:44 -04:00
|
|
|
if (v.isStr())
|
|
|
|
|
strHex = v.getValStr();
|
|
|
|
|
if (!IsHex(strHex))
|
2017-06-21 00:39:47 -04:00
|
|
|
throw std::runtime_error(strName+" must be hexadecimal string (not '"+strHex+"')");
|
2014-07-29 11:12:44 -04:00
|
|
|
return ParseHex(strHex);
|
|
|
|
|
}
|