diff --git a/src/nameclaim.cpp b/src/nameclaim.cpp index 17c448325..c8df56308 100644 --- a/src/nameclaim.cpp +++ b/src/nameclaim.cpp @@ -119,10 +119,57 @@ bool DecodeClaimScript(const CScript& scriptIn, int& op, std::vector OP_PUSHDATA4) + return false; + + if (!scriptIn.GetOp(pc, opcode) || opcode < 0 || opcode > OP_PUSHDATA4) + return false; + + if (!scriptIn.GetOp(pc, opcode)) + return false; + + auto last_drop = OP_DROP; + if (opcode >= 0 && opcode <= OP_PUSHDATA4 && op != OP_CLAIM_NAME) { + if (!scriptIn.GetOp(pc, opcode)) + return false; + last_drop = OP_2DROP; + } else if (op == OP_UPDATE_CLAIM) + return false; + + if (opcode != OP_2DROP) + return false; + + if (!scriptIn.GetOp(pc, opcode) || opcode != last_drop) + return false; + + return !(op == OP_SUPPORT_CLAIM && last_drop == OP_2DROP && !allowSupportMetadata); + +} + + uint160 ClaimIdHash(const uint256& txhash, uint32_t nOut) { std::vector claimToHash(txhash.begin(), txhash.end()); @@ -139,10 +186,10 @@ CScript StripClaimScriptPrefix(const CScript& scriptIn) CScript StripClaimScriptPrefix(const CScript& scriptIn, int& op) { - std::vector > vvchParams; CScript::const_iterator pc = scriptIn.begin(); - if (!DecodeClaimScript(scriptIn, op, vvchParams, pc)) + auto isClaim = DecodeClaimScript(scriptIn, op, pc); + if (!isClaim) return scriptIn; return CScript(pc, scriptIn.end()); diff --git a/src/nameclaim.h b/src/nameclaim.h index 47ebbaf12..d6a9ec23c 100644 --- a/src/nameclaim.h +++ b/src/nameclaim.h @@ -30,6 +30,7 @@ CScript SupportClaimScript(std::string name, uint160 claimId, std::string value= CScript UpdateClaimScript(std::string name, uint160 claimId, std::string value); bool DecodeClaimScript(const CScript& scriptIn, int& op, std::vector >& vvchParams, bool allowSupportMetadata=true); bool DecodeClaimScript(const CScript& scriptIn, int& op, std::vector >& vvchParams, CScript::const_iterator& pc, bool allowSupportMetadata=true); +bool DecodeClaimScript(const CScript& scriptIn, int& op, CScript::const_iterator& pc, bool allowSupportMetadata=true); CScript StripClaimScriptPrefix(const CScript& scriptIn); CScript StripClaimScriptPrefix(const CScript& scriptIn, int& op); uint160 ClaimIdHash(const uint256& txhash, uint32_t nOut); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 42af04529..ffede598a 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3995,7 +3995,8 @@ static UniValue listunspent(const JSONRPCRequest& request) std::vector vecOutputs; { LOCK2(cs_main, pwallet->cs_wallet); - pwallet->AvailableCoins(vecOutputs, !include_unsafe, nullptr, nMinimumAmount, nMaximumAmount, nMinimumSumAmount, nMaximumCount, nMinDepth, nMaxDepth); + pwallet->AvailableCoins(vecOutputs, !include_unsafe, nullptr, + nMinimumAmount, nMaximumAmount, nMinimumSumAmount, nMaximumCount, nMinDepth, nMaxDepth, true); } LOCK(pwallet->cs_wallet); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 88d1bafa2..e0dac9a6b 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1877,7 +1877,8 @@ bool CWalletTx::RelayWalletTransaction(CConnman* connman) CValidationState state; /* GetDepthInMainChain already catches known conflicts. */ if (InMempool() || AcceptToMemoryPool(maxTxFee, state)) { - pwallet->WalletLogPrintf("Relaying wtx %s\n", GetHash().ToString()); + if (LogAcceptCategory(BCLog::DB)) + pwallet->WalletLogPrintf("Relaying wtx %s\n", GetHash().ToString()); if (connman) { CInv inv(MSG_TX, GetHash()); connman->ForEachNode([&inv](CNode* pnode) @@ -2286,7 +2287,9 @@ CAmount CWallet::GetAvailableBalance(const CCoinControl* coinControl) const return balance; } -void CWallet::AvailableCoins(std::vector &vCoins, bool fOnlySafe, const CCoinControl *coinControl, const CAmount &nMinimumAmount, const CAmount &nMaximumAmount, const CAmount &nMinimumSumAmount, const uint64_t nMaximumCount, const int nMinDepth, const int nMaxDepth) const +void CWallet::AvailableCoins(std::vector &vCoins, bool fOnlySafe, const CCoinControl *coinControl, + const CAmount &nMinimumAmount, const CAmount &nMaximumAmount, const CAmount &nMinimumSumAmount, + const uint64_t nMaximumCount, const int nMinDepth, const int nMaxDepth, bool computeSolvable) const { AssertLockHeld(cs_main); AssertLockHeld(cs_wallet); @@ -2373,17 +2376,23 @@ void CWallet::AvailableCoins(std::vector &vCoins, bool fOnlySafe, const continue; } - bool solvable = IsSolvable(*this, pcoin->tx->vout[i].scriptPubKey); - bool spendable = (mine & ISMINE_SPENDABLE) || (((mine & ISMINE_WATCH_ONLY) != ISMINE_NO) && (coinControl && coinControl->fAllowWatchOnly && solvable)); - // spending claims or supports requires specific selection: - auto isClaimCoin = (mine & ISMINE_CLAIM) || (mine & ISMINE_SUPPORT); + auto isClaimCoin = bool(mine & ISMINE_STAKE); auto claimSpendRequested = isClaimCoin && coinControl && coinControl->IsSelected(COutPoint(entry.first, i)); - - if (spendable && isClaimCoin && !claimSpendRequested) + if (isClaimCoin && !claimSpendRequested) continue; - vCoins.push_back(COutput(pcoin, i, nDepth, spendable, solvable, safeTx, (coinControl && coinControl->fAllowWatchOnly))); + bool solvable = false, computedSolvable = false; + bool spendable = bool(mine & ISMINE_SPENDABLE); + if (!spendable && bool(mine & ISMINE_WATCH_ONLY) && coinControl && coinControl->fAllowWatchOnly) { + solvable = IsSolvable(*this, pcoin->tx->vout[i].scriptPubKey); // this is a slow call + spendable = solvable; + computedSolvable = true; + }; + if (computeSolvable && !computedSolvable) + solvable = IsSolvable(*this, pcoin->tx->vout[i].scriptPubKey); + + vCoins.emplace_back(pcoin, i, nDepth, spendable, solvable, safeTx, (coinControl && coinControl->fAllowWatchOnly)); // Checks the sum amount of all UTXO's. if (nMinimumSumAmount != MAX_MONEY) { @@ -3495,7 +3504,8 @@ bool CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRe } m_pool_key_to_index.erase(keypool.vchPubKey.GetID()); - WalletLogPrintf("keypool reserve %d\n", nIndex); + if (LogAcceptCategory(BCLog::DB)) + WalletLogPrintf("keypool reserve %d\n", nIndex); } return true; } @@ -3505,7 +3515,8 @@ void CWallet::KeepKey(int64_t nIndex) // Remove from key pool WalletBatch batch(*database); batch.ErasePool(nIndex); - WalletLogPrintf("keypool keep %d\n", nIndex); + if (LogAcceptCategory(BCLog::DB)) + WalletLogPrintf("keypool keep %d\n", nIndex); } void CWallet::ReturnKey(int64_t nIndex, bool fInternal, const CPubKey& pubkey) diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 33bc2c396..6abef757a 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -508,8 +508,8 @@ public: int i; int nDepth; - /** Pre-computed estimated size of this output as a fully-signed input in a transaction. Can be -1 if it could not be calculated */ - int nInputBytes; + /** estimated size of this output as a fully-signed input in a transaction. Can be -1 */ + mutable int nInputBytes; /** Whether we have the private keys to spend this output */ bool fSpendable; @@ -527,20 +527,22 @@ public: */ bool fSafe; - COutput(const CWalletTx *txIn, int iIn, int nDepthIn, bool fSpendableIn, bool fSolvableIn, bool fSafeIn, bool use_max_sig_in = false) + COutput(const CWalletTx *txIn, int iIn, int nDepthIn, bool fSpendableIn, + bool fSolvableIn, bool fSafeIn, bool use_max_sig_in = false) + : tx(txIn), i(iIn), nDepth(nDepthIn), fSpendable(fSpendableIn), fSolvable(fSolvableIn), + fSafe(fSafeIn), nInputBytes(-1), use_max_sig(use_max_sig_in) { - tx = txIn; i = iIn; nDepth = nDepthIn; fSpendable = fSpendableIn; fSolvable = fSolvableIn; fSafe = fSafeIn; nInputBytes = -1; use_max_sig = use_max_sig_in; - // If known and signable by the given wallet, compute nInputBytes - // Failure will keep this value -1 - if (fSpendable && tx) { - nInputBytes = tx->GetSpendSize(i, use_max_sig); - } } std::string ToString() const; inline CInputCoin GetInputCoin() const { + // If known and signable by the given wallet, compute nInputBytes + // Failure will keep this value -1 + if (nInputBytes < 0 && fSpendable && tx) { + nInputBytes = tx->GetSpendSize(i, use_max_sig); + } return CInputCoin(tx->tx, i, nInputBytes); } }; @@ -850,7 +852,7 @@ public: /** * populate vCoins with vector of available COutputs. */ - void AvailableCoins(std::vector& vCoins, bool fOnlySafe=true, const CCoinControl *coinControl = nullptr, const CAmount& nMinimumAmount = 1, const CAmount& nMaximumAmount = MAX_MONEY, const CAmount& nMinimumSumAmount = MAX_MONEY, const uint64_t nMaximumCount = 0, const int nMinDepth = 0, const int nMaxDepth = 9999999) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); + void AvailableCoins(std::vector& vCoins, bool fOnlySafe=true, const CCoinControl *coinControl = nullptr, const CAmount& nMinimumAmount = 1, const CAmount& nMaximumAmount = MAX_MONEY, const CAmount& nMinimumSumAmount = MAX_MONEY, const uint64_t nMaximumCount = 0, const int nMinDepth = 0, const int nMaxDepth = 9999999, bool computeSolvable=false) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); /** * Return list of available coins and locked coins grouped by non-change output address.