diff --git a/src/script/standard.cpp b/src/script/standard.cpp index bdba59eca..4eab398bb 100644 --- a/src/script/standard.cpp +++ b/src/script/standard.cpp @@ -226,6 +226,20 @@ bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet) { vector vSolutions; txnouttype whichType; + + // if this is a CLTV script, get the destination after CLTV + if (scriptPubKey.IsCheckLockTimeVerify()) + { + uint8_t pushOp = scriptPubKey.data()[0]; + uint32_t scriptStart = pushOp + 3; + + // check post CLTV script + CScript postfix = CScript(scriptPubKey.size() > scriptStart ? scriptPubKey.begin() + scriptStart : scriptPubKey.end(), scriptPubKey.end()); + + // check again with only postfix subscript + return(ExtractDestination(postfix, addressRet)); + } + if (!Solver(scriptPubKey, whichType, vSolutions)) return false; @@ -260,6 +274,20 @@ bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, vecto addressRet.clear(); typeRet = TX_NONSTANDARD; vector vSolutions; + + // if this is a CLTV script, get the destinations after CLTV + if (scriptPubKey.IsCheckLockTimeVerify()) + { + uint8_t pushOp = scriptPubKey.data()[0]; + uint32_t scriptStart = pushOp + 3; + + // check post CLTV script + CScript postfix = CScript(scriptPubKey.size() > scriptStart ? scriptPubKey.begin() + scriptStart : scriptPubKey.end(), scriptPubKey.end()); + + // check again with only postfix subscript + return(ExtractDestinations(postfix, typeRet, addressRet, nRequiredRet)); + } + if (!Solver(scriptPubKey, typeRet, vSolutions)) return false; if (typeRet == TX_NULL_DATA){ diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 170014885..e0d7bc8ac 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1395,7 +1395,7 @@ isminetype CWallet::IsMine(const CTxIn &txin) const { const CWalletTx& prev = (*mi).second; if (txin.prevout.n < prev.vout.size()) - return IsMine(prev, txin.prevout.n); + return (::IsMine(*this, prev.vout[txin.prevout.n].scriptPubKey)); } } return ISMINE_NO; @@ -1410,7 +1410,7 @@ CAmount CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const { const CWalletTx& prev = (*mi).second; if (txin.prevout.n < prev.vout.size()) - if (IsMine(prev, txin.prevout.n) & filter) + if (::IsMine(*this, prev.vout[txin.prevout.n].scriptPubKey) & filter) return prev.vout[txin.prevout.n].nValue; // komodo_interest? } } @@ -1458,6 +1458,9 @@ CAmount CWallet::GetChange(const CTxOut& txout) const return (IsChange(txout) ? txout.nValue : 0); } +typedef vector valtype; +unsigned int HaveKeys(const vector& pubkeys, const CKeyStore& keystore); + bool CWallet::IsMine(const CTransaction& tx) { for (int i = 0; i < tx.vout.size(); i++) @@ -1468,26 +1471,9 @@ bool CWallet::IsMine(const CTransaction& tx) return false; } -// special case handling for CLTV scripts, this does not error check to ensure the script is CLTV and is -// only internal to the wallet for that reason. -isminetype CWallet::IsCLTVMine(CScript &script, CScriptID &scriptID) const -{ - uint8_t pushOp = script.data()[0]; - uint32_t scriptStart = pushOp + 3; - - // check post CLTV script - CScript postfix = CScript(script.size() > scriptStart ? script.begin() + scriptStart : script.end(), script.end()); - - // check again with postfix subscript - return(::IsMine(*this, postfix)); -} - -typedef vector valtype; -unsigned int HaveKeys(const vector& pubkeys, const CKeyStore& keystore); - // special case handling for non-standard/Verus OP_RETURN script outputs, which need the transaction // to determine ownership -isminetype CWallet::IsMine(const CTransaction& tx, uint32_t voutNum) const +isminetype CWallet::IsMine(const CTransaction& tx, uint32_t voutNum) { vector vSolutions; txnouttype whichType; @@ -1529,7 +1515,7 @@ isminetype CWallet::IsMine(const CTransaction& tx, uint32_t voutNum) const // if this is a CLTV, handle it differently if (subscript.IsCheckLockTimeVerify()) { - return this->IsCLTVMine(subscript, scriptID); + return (::IsMine(*this, subscript)); } else { @@ -1556,7 +1542,14 @@ isminetype CWallet::IsMine(const CTransaction& tx, uint32_t voutNum) const if (CScriptID(opretScript) == scriptID && opretScript.IsCheckLockTimeVerify()) { - return this->IsCLTVMine(opretScript, scriptID); + // if we find that this is ours, we need to add this script to the wallet, + // and we can then recognize this transaction + isminetype t = ::IsMine(*this, opretScript); + if (t != ISMINE_NO) + { + this->AddCScript(opretScript); + } + return t; } } } @@ -1612,7 +1605,7 @@ CAmount CWallet::GetCredit(const CTransaction& tx, int32_t voutNum, const ismine { if (voutNum >= tx.vout.size() || !MoneyRange(tx.vout[voutNum].nValue)) throw std::runtime_error("CWallet::GetCredit(): value out of range"); - return ((IsMine(tx, voutNum) & filter) ? tx.vout[voutNum].nValue : 0); + return ((IsMine(tx.vout[voutNum]) & filter) ? tx.vout[voutNum].nValue : 0); } CAmount CWallet::GetCredit(const CTransaction& tx, const isminefilter& filter) const @@ -2397,7 +2390,7 @@ void CWallet::AvailableCoins(vector& vCoins, bool fOnlyConfirmed, const for (int i = 0; i < pcoin->vout.size(); i++) { - isminetype mine = IsMine(*pcoin, i); + isminetype mine = IsMine(pcoin->vout[i]); if (!(IsSpent(wtxid, i)) && mine != ISMINE_NO && !IsLockedCoin((*it).first, i) && (pcoin->vout[i].nValue > 0 || fIncludeZeroValue) && (!coinControl || !coinControl->HasSelected() || coinControl->IsSelected((*it).first, i))) diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index e1dc30a3a..52a92e86c 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -762,9 +762,6 @@ private: template void SyncMetaData(std::pair::iterator, typename TxSpendMap::iterator>); - // parses a CLTV script followed by a standard script and determines ownership - isminetype IsCLTVMine(CScript &subScript, CScriptID &scriptID) const; - protected: bool UpdatedNoteData(const CWalletTx& wtxIn, CWalletTx& wtx); void MarkAffectedTransactionsDirty(const CTransaction& tx); @@ -1050,7 +1047,7 @@ public: isminetype IsMine(const CTxIn& txin) const; CAmount GetDebit(const CTxIn& txin, const isminefilter& filter) const; isminetype IsMine(const CTxOut& txout) const; - isminetype IsMine(const CTransaction& tx, uint32_t voutNum) const; + isminetype IsMine(const CTransaction& tx, uint32_t voutNum); CAmount GetCredit(const CTxOut& txout, const isminefilter& filter) const; bool IsChange(const CTxOut& txout) const; CAmount GetChange(const CTxOut& txout) const; diff --git a/src/wallet/wallet_ismine.cpp b/src/wallet/wallet_ismine.cpp index 5e144eabe..2a2a29ea7 100644 --- a/src/wallet/wallet_ismine.cpp +++ b/src/wallet/wallet_ismine.cpp @@ -34,10 +34,21 @@ isminetype IsMine(const CKeyStore &keystore, const CTxDestination& dest) return IsMine(keystore, script); } -isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) +isminetype IsMine(const CKeyStore &keystore, const CScript& _scriptPubKey) { vector vSolutions; txnouttype whichType; + CScript scriptPubKey = _scriptPubKey; + + if (scriptPubKey.IsCheckLockTimeVerify()) + { + uint8_t pushOp = scriptPubKey.data()[0]; + uint32_t scriptStart = pushOp + 3; + + // continue with post CLTV script + scriptPubKey = CScript(scriptPubKey.size() > scriptStart ? scriptPubKey.begin() + scriptStart : scriptPubKey.end(), scriptPubKey.end()); + } + if (!Solver(scriptPubKey, whichType, vSolutions)) { if (keystore.HaveWatchOnly(scriptPubKey)) return ISMINE_WATCH_ONLY;