Any projects which want to use Hush code from now on will need to be licensed as GPLv3 or we will send the lawyers: https://www.softwarefreedom.org/ Notably, Komodo (KMD) is licensed as GPLv2 and is no longer compatible to receive code changes, without causing legal issues. MIT projects, such as Zcash, also cannot pull in changes from the Hush Full Node without permission from The Hush Developers, which may in some circumstances grant an MIT license on a case-by-case basis.
169 lines
5.6 KiB
C++
169 lines
5.6 KiB
C++
// Copyright (c) 2009-2014 The Bitcoin Core developers
|
|
// Distributed under the GPLv3 software license, see the accompanying
|
|
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
|
|
|
/******************************************************************************
|
|
* Copyright © 2014-2019 The SuperNET Developers. *
|
|
* *
|
|
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
|
|
* the top-level directory of this distribution for the individual copyright *
|
|
* holder information and the developer policies on copyright and licensing. *
|
|
* *
|
|
* Unless otherwise agreed in a custom licensing agreement, no part of the *
|
|
* SuperNET software, including this file may be copied, modified, propagated *
|
|
* or distributed except according to the terms contained in the LICENSE file *
|
|
* *
|
|
* Removal or modification of this copyright notice is prohibited. *
|
|
* *
|
|
******************************************************************************/
|
|
|
|
#include "core_io.h"
|
|
|
|
#include "primitives/block.h"
|
|
#include "primitives/transaction.h"
|
|
#include "script/script.h"
|
|
#include "serialize.h"
|
|
#include "streams.h"
|
|
#include <univalue.h>
|
|
#include "util.h"
|
|
#include "utilstrencodings.h"
|
|
#include "version.h"
|
|
|
|
#include <boost/algorithm/string/classification.hpp>
|
|
#include <boost/algorithm/string/predicate.hpp>
|
|
#include <boost/algorithm/string/replace.hpp>
|
|
#include <boost/algorithm/string/split.hpp>
|
|
#include <boost/assign/list_of.hpp>
|
|
|
|
using namespace std;
|
|
|
|
CScript ParseScript(const std::string& s)
|
|
{
|
|
CScript result;
|
|
|
|
static map<string, opcodetype> mapOpNames;
|
|
|
|
if (mapOpNames.empty())
|
|
{
|
|
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:
|
|
boost::algorithm::replace_first(strName, "OP_", "");
|
|
mapOpNames[strName] = (opcodetype)op;
|
|
}
|
|
}
|
|
|
|
vector<string> words;
|
|
boost::algorithm::split(words, s, boost::algorithm::is_any_of(" \t\n"), boost::algorithm::token_compress_on);
|
|
|
|
for (std::vector<std::string>::const_iterator w = words.begin(); w != words.end(); ++w)
|
|
{
|
|
if (w->empty())
|
|
{
|
|
// Empty string, ignore. (boost::split given '' will return one word)
|
|
}
|
|
else if (all(*w, boost::algorithm::is_digit()) ||
|
|
(boost::algorithm::starts_with(*w, "-") && all(string(w->begin()+1, w->end()), boost::algorithm::is_digit())))
|
|
{
|
|
// Number
|
|
int64_t n = atoi64(*w);
|
|
result << n;
|
|
}
|
|
else if (boost::algorithm::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<unsigned char> raw = ParseHex(string(w->begin()+2, w->end()));
|
|
result.insert(result.end(), raw.begin(), raw.end());
|
|
}
|
|
else if (w->size() >= 2 && boost::algorithm::starts_with(*w, "'") && boost::algorithm::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<unsigned char> 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)
|
|
{
|
|
if (!IsHex(strHexTx))
|
|
return false;
|
|
|
|
vector<unsigned char> txData(ParseHex(strHexTx));
|
|
CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
|
|
try {
|
|
ssData >> tx;
|
|
}
|
|
catch (const std::exception&) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool DecodeHexBlk(CBlock& block, const std::string& strHexBlk)
|
|
{
|
|
if (!IsHex(strHexBlk))
|
|
return false;
|
|
|
|
std::vector<unsigned char> blockData(ParseHex(strHexBlk));
|
|
CDataStream ssBlock(blockData, SER_NETWORK, PROTOCOL_VERSION);
|
|
try {
|
|
ssBlock >> block;
|
|
}
|
|
catch (const std::exception&) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
uint256 ParseHashUV(const UniValue& v, const string& strName)
|
|
{
|
|
string strHex;
|
|
if (v.isStr())
|
|
strHex = v.getValStr();
|
|
return ParseHashStr(strHex, strName); // Note: ParseHashStr("") throws a runtime_error
|
|
}
|
|
|
|
uint256 ParseHashStr(const std::string& strHex, const std::string& strName)
|
|
{
|
|
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<unsigned char> 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);
|
|
}
|