restored nonstandard output on getrawtransaction

attempting to make index pointer problems more obvious


reverted strip in Solver


synced subtype
This commit is contained in:
Brannon King 2019-09-13 11:01:43 -06:00
parent 920a9b09dc
commit 4da4ab1995
15 changed files with 66 additions and 44 deletions

View file

@ -15,6 +15,7 @@
#include <util.h> #include <util.h>
#include <utilmoneystr.h> #include <utilmoneystr.h>
#include <utilstrencodings.h> #include <utilstrencodings.h>
#include <nameclaim.h>
UniValue ValueFromAmount(const CAmount& amount) UniValue ValueFromAmount(const CAmount& amount)
{ {
@ -147,12 +148,20 @@ void ScriptToUniv(const CScript& script, UniValue& out, bool include_address)
out.pushKV("hex", HexStr(script.begin(), script.end())); out.pushKV("hex", HexStr(script.begin(), script.end()));
std::vector<std::vector<unsigned char>> solns; std::vector<std::vector<unsigned char>> solns;
txnouttype type; txnouttype type; int claimOp;
Solver(script, type, solns); auto stripped = StripClaimScriptPrefix(script, claimOp);
out.pushKV("type", GetTxnOutputType(type)); Solver(stripped, type, solns);
if (claimOp >= 0) {
out.pushKV("isclaim", UniValue(claimOp == OP_CLAIM_NAME || claimOp == OP_UPDATE_CLAIM));
out.pushKV("issupport", UniValue(claimOp == OP_SUPPORT_CLAIM));
out.pushKV("subtype", GetTxnOutputType(type));
out.pushKV("type", GetTxnOutputType(TX_NONSTANDARD)); // trying to keep backwards compatibility
}
else
out.pushKV("type", GetTxnOutputType(type)); // trying to keep backwards compatibility
CTxDestination address; CTxDestination address;
if (include_address && ExtractDestination(script, address)) { if (include_address && ExtractDestination(stripped, address)) {
out.pushKV("address", EncodeDestination(address)); out.pushKV("address", EncodeDestination(address));
} }
} }
@ -168,19 +177,27 @@ void ScriptPubKeyToUniv(const CScript& scriptPubKey,
if (fIncludeHex) if (fIncludeHex)
out.pushKV("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end())); out.pushKV("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end()));
if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired)) { int claimOp;
auto stripped = StripClaimScriptPrefix(scriptPubKey, claimOp);
auto extracted = ExtractDestinations(stripped, type, addresses, nRequired);
if (claimOp >= 0) {
out.pushKV("isclaim", UniValue(claimOp == OP_CLAIM_NAME || claimOp == OP_UPDATE_CLAIM));
out.pushKV("issupport", UniValue(claimOp == OP_SUPPORT_CLAIM));
out.pushKV("subtype", GetTxnOutputType(type));
out.pushKV("type", GetTxnOutputType(TX_NONSTANDARD));
}
else
out.pushKV("type", GetTxnOutputType(type)); out.pushKV("type", GetTxnOutputType(type));
return;
}
out.pushKV("reqSigs", nRequired); if (extracted) {
out.pushKV("type", GetTxnOutputType(type)); out.pushKV("reqSigs", nRequired);
UniValue a(UniValue::VARR);
UniValue a(UniValue::VARR); for (const CTxDestination &addr : addresses) {
for (const CTxDestination& addr : addresses) { a.push_back(EncodeDestination(addr));
a.push_back(EncodeDestination(addr)); }
out.pushKV("addresses", a);
} }
out.pushKV("addresses", a);
} }
void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry, bool include_hex, int serialize_flags) void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry, bool include_hex, int serialize_flags)

View file

@ -193,6 +193,7 @@ bool CDBWrapper::WriteBatch(CDBBatch& batch, bool fSync)
if (log_memory) { if (log_memory) {
mem_before = DynamicMemoryUsage() / 1024.0 / 1024; mem_before = DynamicMemoryUsage() / 1024.0 / 1024;
} }
assert(pdb);
leveldb::Status status = pdb->Write(fSync ? syncoptions : writeoptions, &batch.batch); leveldb::Status status = pdb->Write(fSync ? syncoptions : writeoptions, &batch.batch);
dbwrapper_private::HandleError(status); dbwrapper_private::HandleError(status);
if (log_memory) { if (log_memory) {

View file

@ -151,7 +151,7 @@ public:
* with a zero'd byte array. * with a zero'd byte array.
*/ */
CDBWrapper(const fs::path& path, size_t nCacheSize, bool fMemory = false, bool fWipe = false, bool obfuscate = false); CDBWrapper(const fs::path& path, size_t nCacheSize, bool fMemory = false, bool fWipe = false, bool obfuscate = false);
~CDBWrapper(); virtual ~CDBWrapper();
CDBWrapper(const CDBWrapper&) = delete; CDBWrapper(const CDBWrapper&) = delete;
/* CDBWrapper& operator=(const CDBWrapper&) = delete; */ /* CDBWrapper& operator=(const CDBWrapper&) = delete; */
@ -159,6 +159,7 @@ public:
template <typename K, typename V> template <typename K, typename V>
bool Read(const K& key, V& value) const bool Read(const K& key, V& value) const
{ {
assert(ssKey.empty());
ssKey << key; ssKey << key;
leveldb::Slice slKey(ssKey.data(), ssKey.size()); leveldb::Slice slKey(ssKey.data(), ssKey.size());

View file

@ -28,6 +28,8 @@ protected:
DB(const fs::path& path, size_t n_cache_size, DB(const fs::path& path, size_t n_cache_size,
bool f_memory = false, bool f_wipe = false, bool f_obfuscate = false); bool f_memory = false, bool f_wipe = false, bool f_obfuscate = false);
~DB() override {}
/// Read block locator of the chain that the txindex is in sync with. /// Read block locator of the chain that the txindex is in sync with.
bool ReadBestBlock(CBlockLocator& locator) const; bool ReadBestBlock(CBlockLocator& locator) const;

View file

@ -29,6 +29,7 @@ class TxIndex::DB : public BaseIndex::DB
{ {
public: public:
explicit DB(size_t n_cache_size, bool f_memory = false, bool f_wipe = false); explicit DB(size_t n_cache_size, bool f_memory = false, bool f_wipe = false);
~DB() override {}
/// Read the disk location of the transaction data with the given hash. Returns false if the /// Read the disk location of the transaction data with the given hash. Returns false if the
/// transaction hash is not indexed. /// transaction hash is not indexed.

View file

@ -115,7 +115,7 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason)
unsigned int nDataOut = 0; unsigned int nDataOut = 0;
txnouttype whichType; txnouttype whichType;
for (const CTxOut& txout : tx.vout) { for (const CTxOut& txout : tx.vout) {
if (!::IsStandard(txout.scriptPubKey, whichType)) { if (!::IsStandard(StripClaimScriptPrefix(txout.scriptPubKey), whichType)) {
reason = "scriptpubkey"; reason = "scriptpubkey";
return false; return false;
} }

View file

@ -45,7 +45,7 @@ static const unsigned int MAX_STANDARD_P2WSH_SCRIPT_SIZE = 3600;
* standard and should be done with care and ideally rarely. It makes sense to * standard and should be done with care and ideally rarely. It makes sense to
* only increase the dust limit after prior releases were already not creating * only increase the dust limit after prior releases were already not creating
* outputs below the new threshold */ * outputs below the new threshold */
static const unsigned int DUST_RELAY_TX_FEE = 3000; static const unsigned int DUST_RELAY_TX_FEE = 1000;
/** /**
* Standard script verification flags that standard transactions will comply * Standard script verification flags that standard transactions will comply
* with. However scripts violating these flags may still be present in valid * with. However scripts violating these flags may still be present in valid

View file

@ -111,7 +111,7 @@ std::string escapeNonUtf8(const std::string& name)
static bool extractValue(const CScript& scriptPubKey, std::string& sValue) static bool extractValue(const CScript& scriptPubKey, std::string& sValue)
{ {
int op; int op;
std::vector<std::vector<unsigned char> > vvchParams; std::vector<std::vector<unsigned char>> vvchParams;
if (!DecodeClaimScript(scriptPubKey, op, vvchParams)) if (!DecodeClaimScript(scriptPubKey, op, vvchParams))
return false; return false;

View file

@ -549,14 +549,15 @@ static UniValue decoderawtransaction(const JSONRPCRequest& request)
" ],\n" " ],\n"
" \"vout\" : [ (array of json objects)\n" " \"vout\" : [ (array of json objects)\n"
" {\n" " {\n"
" \"value\" : x.xxx, (numeric) The value in " + CURRENCY_UNIT + "\n" " \"value\" : x.xxx, (numeric) The value in " + CURRENCY_UNIT + "\n"
" \"n\" : n, (numeric) index\n" " \"n\" : n, (numeric) index\n"
" \"scriptPubKey\" : { (json object)\n" " \"scriptPubKey\" : { (json object)\n"
" \"asm\" : \"asm\", (string) the asm\n" " \"asm\" : \"asm\", (string) the asm\n"
" \"hex\" : \"hex\", (string) the hex\n" " \"hex\" : \"hex\", (string) the hex\n"
" \"reqSigs\" : n, (numeric) The required sigs\n" " \"reqSigs\" : n, (numeric) The required sigs\n"
" \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n" " \"subtype\" : \"pubkeyhash\", (numeric) For claims and supports, this represents the type of suffix\n"
" \"addresses\" : [ (json array of string)\n" " \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n"
" \"addresses\" : [ (json array of string)\n"
" \"12tvKAXCxZjSmdNbao16dKXC8tRWfcF5oc\" (string) lbry address\n" " \"12tvKAXCxZjSmdNbao16dKXC8tRWfcF5oc\" (string) lbry address\n"
" ,...\n" " ,...\n"
" ]\n" " ]\n"

View file

@ -6,6 +6,7 @@
#include <script/sign.h> #include <script/sign.h>
#include <key.h> #include <key.h>
#include <nameclaim.h>
#include <policy/policy.h> #include <policy/policy.h>
#include <primitives/transaction.h> #include <primitives/transaction.h>
#include <script/standard.h> #include <script/standard.h>
@ -183,7 +184,7 @@ bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreato
std::vector<valtype> result; std::vector<valtype> result;
txnouttype whichType; txnouttype whichType;
bool solved = SignStep(provider, creator, fromPubKey, result, whichType, SigVersion::BASE, sigdata); bool solved = SignStep(provider, creator, StripClaimScriptPrefix(fromPubKey), result, whichType, SigVersion::BASE, sigdata);
bool P2SH = false; bool P2SH = false;
CScript subscript; CScript subscript;
sigdata.scriptWitness.stack.clear(); sigdata.scriptWitness.stack.clear();
@ -349,7 +350,7 @@ SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nI
// Get scripts // Get scripts
txnouttype script_type; txnouttype script_type;
std::vector<std::vector<unsigned char>> solutions; std::vector<std::vector<unsigned char>> solutions;
Solver(txout.scriptPubKey, script_type, solutions); Solver(StripClaimScriptPrefix(txout.scriptPubKey), script_type, solutions);
SigVersion sigversion = SigVersion::BASE; SigVersion sigversion = SigVersion::BASE;
CScript next_script = txout.scriptPubKey; CScript next_script = txout.scriptPubKey;

View file

@ -91,21 +91,19 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::v
{ {
vSolutionsRet.clear(); vSolutionsRet.clear();
auto strippedPubKey = StripClaimScriptPrefix(scriptPubKey);
// Shortcut for pay-to-script-hash, which are more constrained than the other types: // Shortcut for pay-to-script-hash, which are more constrained than the other types:
// it is always OP_HASH160 20 [20 byte hash] OP_EQUAL // it is always OP_HASH160 20 [20 byte hash] OP_EQUAL
if (strippedPubKey.IsPayToScriptHash()) if (scriptPubKey.IsPayToScriptHash())
{ {
typeRet = TX_SCRIPTHASH; typeRet = TX_SCRIPTHASH;
std::vector<unsigned char> hashBytes(strippedPubKey.begin()+2, strippedPubKey.begin()+22); std::vector<unsigned char> hashBytes(scriptPubKey.begin()+2, scriptPubKey.begin()+22);
vSolutionsRet.push_back(hashBytes); vSolutionsRet.push_back(hashBytes);
return true; return true;
} }
int witnessversion; int witnessversion;
std::vector<unsigned char> witnessprogram; std::vector<unsigned char> witnessprogram;
if (strippedPubKey.IsWitnessProgram(witnessversion, witnessprogram)) { if (scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
if (witnessversion == 0 && witnessprogram.size() == WITNESS_V0_KEYHASH_SIZE) { if (witnessversion == 0 && witnessprogram.size() == WITNESS_V0_KEYHASH_SIZE) {
typeRet = TX_WITNESS_V0_KEYHASH; typeRet = TX_WITNESS_V0_KEYHASH;
vSolutionsRet.push_back(witnessprogram); vSolutionsRet.push_back(witnessprogram);
@ -131,19 +129,19 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::v
// So long as script passes the IsUnspendable() test and all but the first // So long as script passes the IsUnspendable() test and all but the first
// byte passes the IsPushOnly() test we don't care what exactly is in the // byte passes the IsPushOnly() test we don't care what exactly is in the
// script. // script.
if (strippedPubKey.size() >= 1 && strippedPubKey[0] == OP_RETURN && strippedPubKey.IsPushOnly(strippedPubKey.begin()+1)) { if (scriptPubKey.size() >= 1 && scriptPubKey[0] == OP_RETURN && scriptPubKey.IsPushOnly(scriptPubKey.begin()+1)) {
typeRet = TX_NULL_DATA; typeRet = TX_NULL_DATA;
return true; return true;
} }
std::vector<unsigned char> data; std::vector<unsigned char> data;
if (MatchPayToPubkey(strippedPubKey, data)) { if (MatchPayToPubkey(scriptPubKey, data)) {
typeRet = TX_PUBKEY; typeRet = TX_PUBKEY;
vSolutionsRet.push_back(std::move(data)); vSolutionsRet.push_back(std::move(data));
return true; return true;
} }
if (MatchPayToPubkeyHash(strippedPubKey, data)) { if (MatchPayToPubkeyHash(scriptPubKey, data)) {
typeRet = TX_PUBKEYHASH; typeRet = TX_PUBKEYHASH;
vSolutionsRet.push_back(std::move(data)); vSolutionsRet.push_back(std::move(data));
return true; return true;
@ -151,7 +149,7 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::v
unsigned int required; unsigned int required;
std::vector<std::vector<unsigned char>> keys; std::vector<std::vector<unsigned char>> keys;
if (MatchMultisig(strippedPubKey, required, keys)) { if (MatchMultisig(scriptPubKey, required, keys)) {
typeRet = TX_MULTISIG; typeRet = TX_MULTISIG;
vSolutionsRet.push_back({static_cast<unsigned char>(required)}); // safe as required is in range 1..16 vSolutionsRet.push_back({static_cast<unsigned char>(required)}); // safe as required is in range 1..16
vSolutionsRet.insert(vSolutionsRet.end(), keys.begin(), keys.end()); vSolutionsRet.insert(vSolutionsRet.end(), keys.begin(), keys.end());
@ -168,7 +166,7 @@ bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
{ {
std::vector<valtype> vSolutions; std::vector<valtype> vSolutions;
txnouttype whichType; txnouttype whichType;
if (!Solver(scriptPubKey, whichType, vSolutions)) if (!Solver(StripClaimScriptPrefix(scriptPubKey), whichType, vSolutions))
return false; return false;
if (whichType == TX_PUBKEY) if (whichType == TX_PUBKEY)
@ -216,9 +214,8 @@ bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::
addressRet.clear(); addressRet.clear();
typeRet = TX_NONSTANDARD; typeRet = TX_NONSTANDARD;
std::vector<valtype> vSolutions; std::vector<valtype> vSolutions;
if (!Solver(scriptPubKey, typeRet, vSolutions)) auto solved = Solver(scriptPubKey, typeRet, vSolutions);
return false; if (!solved || typeRet == TX_NULL_DATA){
if (typeRet == TX_NULL_DATA){
// This is data, not addresses // This is data, not addresses
return false; return false;
} }

View file

@ -224,6 +224,7 @@ CMutableTransaction ClaimTrieChainFixture::MakeSupport(const CTransaction &prev,
uint32_t prevout = prev.vout.size() - 1; uint32_t prevout = prev.vout.size() - 1;
while (prevout > 0 && prev.vout[prevout].nValue < quantity) while (prevout > 0 && prev.vout[prevout].nValue < quantity)
--prevout; --prevout;
CMutableTransaction tx = BuildTransaction(prev, prevout, prev.vout[prevout].nValue > quantity ? 2 : 1); CMutableTransaction tx = BuildTransaction(prev, prevout, prev.vout[prevout].nValue > quantity ? 2 : 1);
tx.vout[0].scriptPubKey = SupportClaimScript(name, ClaimIdHash(claimtx.GetHash(), 0)); tx.vout[0].scriptPubKey = SupportClaimScript(name, ClaimIdHash(claimtx.GetHash(), 0));
tx.vout[0].nValue = quantity; tx.vout[0].nValue = quantity;

View file

@ -701,7 +701,7 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
// Check dust with default relay fee: // Check dust with default relay fee:
CAmount nDustThreshold = 182 * dustRelayFee.GetFeePerK()/1000; CAmount nDustThreshold = 182 * dustRelayFee.GetFeePerK()/1000;
BOOST_CHECK_EQUAL(nDustThreshold, 546); BOOST_CHECK_EQUAL(nDustThreshold, 182);
// dust: // dust:
t.vout[0].nValue = nDustThreshold - 1; t.vout[0].nValue = nDustThreshold - 1;
BOOST_CHECK(!IsStandardTx(t, reason)); BOOST_CHECK(!IsStandardTx(t, reason));

View file

@ -918,7 +918,7 @@ UniValue supportclaim(const JSONRPCRequest& request)
CClaimTrieCache trieCache(pclaimTrie); CClaimTrieCache trieCache(pclaimTrie);
auto csToName = trieCache.getClaimsForName(sName); auto csToName = trieCache.getClaimsForName(sName);
if (csToName.claimsNsupports.empty()) if (csToName.claimsNsupports.empty())
return NullUniValue; throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Unable to find a claim named %s", sName));
auto& claimNsupports = !sClaimId.empty() ? csToName.find(sClaimId) : csToName.claimsNsupports[0]; auto& claimNsupports = !sClaimId.empty() ? csToName.find(sClaimId) : csToName.claimsNsupports[0];
if (claimNsupports.IsNull()) if (claimNsupports.IsNull())
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Unable to find a claimid that starts with %s", sClaimId)); throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Unable to find a claimid that starts with %s", sClaimId));

View file

@ -166,7 +166,7 @@ public:
txnouttype type; txnouttype type;
std::vector<CTxDestination> vDest; std::vector<CTxDestination> vDest;
int nRequired; int nRequired;
if (ExtractDestinations(script, type, vDest, nRequired)) { if (ExtractDestinations(StripClaimScriptPrefix(script), type, vDest, nRequired)) {
for (const CTxDestination &dest : vDest) for (const CTxDestination &dest : vDest)
boost::apply_visitor(*this, dest); boost::apply_visitor(*this, dest);
} }