restored nonstandard output on getrawtransaction
attempting to make index pointer problems more obvious reverted strip in Solver synced subtype
This commit is contained in:
parent
920a9b09dc
commit
4da4ab1995
15 changed files with 66 additions and 44 deletions
|
@ -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,20 +177,28 @@ 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;
|
||||||
out.pushKV("type", GetTxnOutputType(type));
|
auto stripped = StripClaimScriptPrefix(scriptPubKey, claimOp);
|
||||||
return;
|
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("reqSigs", nRequired);
|
|
||||||
out.pushKV("type", GetTxnOutputType(type));
|
out.pushKV("type", GetTxnOutputType(type));
|
||||||
|
|
||||||
|
if (extracted) {
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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());
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -555,6 +555,7 @@ static UniValue decoderawtransaction(const JSONRPCRequest& request)
|
||||||
" \"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"
|
||||||
|
" \"subtype\" : \"pubkeyhash\", (numeric) For claims and supports, this represents the type of suffix\n"
|
||||||
" \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n"
|
" \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n"
|
||||||
" \"addresses\" : [ (json array of string)\n"
|
" \"addresses\" : [ (json array of string)\n"
|
||||||
" \"12tvKAXCxZjSmdNbao16dKXC8tRWfcF5oc\" (string) lbry address\n"
|
" \"12tvKAXCxZjSmdNbao16dKXC8tRWfcF5oc\" (string) lbry address\n"
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue