Recognizing CLTV transactions more broadly

This commit is contained in:
miketout
2018-05-08 13:33:14 -07:00
parent fab1429d48
commit ea340a1443
4 changed files with 58 additions and 29 deletions

View File

@@ -226,6 +226,20 @@ bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
{
vector<valtype> 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<valtype> 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){

View File

@@ -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<unsigned char> valtype;
unsigned int HaveKeys(const vector<valtype>& 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<unsigned char> valtype;
unsigned int HaveKeys(const vector<valtype>& 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<valtype> 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<COutput>& 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)))

View File

@@ -762,9 +762,6 @@ private:
template <class T>
void SyncMetaData(std::pair<typename TxSpendMap<T>::iterator, typename TxSpendMap<T>::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;

View File

@@ -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<valtype> 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;