optimizing the wallet to better handle claimname calls

This commit is contained in:
Brannon King 2020-02-14 16:30:11 -07:00
parent 24fedd6f14
commit 18e4372eb9
5 changed files with 87 additions and 25 deletions

View file

@ -119,10 +119,57 @@ bool DecodeClaimScript(const CScript& scriptIn, int& op, std::vector<std::vector
vvchParams.push_back(std::move(vchParam2));
if (last_drop == OP_2DROP)
vvchParams.push_back(std::move(vchParam3));
return true;
}
// this overload exists because optimizer wouldn't inline GetScriptOp:
bool DecodeClaimScript(const CScript& scriptIn, int& op, CScript::const_iterator& pc, bool allowSupportMetadata)
{
op = -1;
opcodetype opcode;
if (!scriptIn.GetOp(pc, opcode))
return false;
if (opcode != OP_CLAIM_NAME && opcode != OP_SUPPORT_CLAIM && opcode != OP_UPDATE_CLAIM)
return false;
op = opcode;
// Valid formats:
// OP_CLAIM_NAME vchName vchValue OP_2DROP OP_DROP pubkeyscript
// OP_UPDATE_CLAIM vchName vchClaimId vchValue OP_2DROP OP_2DROP pubkeyscript
// OP_SUPPORT_CLAIM vchName vchClaimId OP_2DROP OP_DROP pubkeyscript
// OP_SUPPORT_CLAIM vchName vchClaimId vchValue OP_2DROP OP_2DROP pubkeyscript
// All others are invalid.
if (!scriptIn.GetOp(pc, opcode) || opcode < 0 || opcode > 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<unsigned char> claimToHash(txhash.begin(), txhash.end());
@ -139,10 +186,10 @@ CScript StripClaimScriptPrefix(const CScript& scriptIn)
CScript StripClaimScriptPrefix(const CScript& scriptIn, int& op)
{
std::vector<std::vector<unsigned char> > 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());

View file

@ -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<std::vector<unsigned char> >& vvchParams, bool allowSupportMetadata=true);
bool DecodeClaimScript(const CScript& scriptIn, int& op, std::vector<std::vector<unsigned char> >& 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);

View file

@ -3995,7 +3995,8 @@ static UniValue listunspent(const JSONRPCRequest& request)
std::vector<COutput> 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);

View file

@ -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<COutput> &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<COutput> &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<COutput> &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)

View file

@ -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<COutput>& 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<COutput>& 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.