Merge pull request #4937

ccca27a [Wallet] Watch-only fixes (Cozz Lovan)
This commit is contained in:
Wladimir J. van der Laan 2014-10-13 13:56:54 +02:00
commit d7e1950483
No known key found for this signature in database
GPG key ID: 74810B012346C9A6
10 changed files with 70 additions and 13 deletions

View file

@ -67,6 +67,13 @@ bool CBasicKeyStore::AddWatchOnly(const CScript &dest)
return true;
}
bool CBasicKeyStore::RemoveWatchOnly(const CScript &dest)
{
LOCK(cs_KeyStore);
setWatchOnly.erase(dest);
return true;
}
bool CBasicKeyStore::HaveWatchOnly(const CScript &dest) const
{
LOCK(cs_KeyStore);

View file

@ -40,6 +40,7 @@ public:
// Support for Watch-only addresses
virtual bool AddWatchOnly(const CScript &dest) =0;
virtual bool RemoveWatchOnly(const CScript &dest) =0;
virtual bool HaveWatchOnly(const CScript &dest) const =0;
virtual bool HaveWatchOnly() const =0;
};
@ -98,6 +99,7 @@ public:
virtual bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const;
virtual bool AddWatchOnly(const CScript &dest);
virtual bool RemoveWatchOnly(const CScript &dest);
virtual bool HaveWatchOnly(const CScript &dest) const;
virtual bool HaveWatchOnly() const;
};

View file

@ -32,7 +32,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
{
QList<TransactionRecord> parts;
int64_t nTime = wtx.GetTxTime();
CAmount nCredit = wtx.GetCredit(true);
CAmount nCredit = wtx.GetCredit(ISMINE_ALL);
CAmount nDebit = wtx.GetDebit(ISMINE_ALL);
CAmount nNet = nCredit - nDebit;
uint256 hash = wtx.GetHash();

View file

@ -605,7 +605,8 @@ void WalletModel::listCoins(std::map<QString, std::vector<COutput> >& mapCoins)
int nDepth = wallet->mapWallet[outpoint.hash].GetDepthInMainChain();
if (nDepth < 0) continue;
COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, nDepth, true);
vCoins.push_back(out);
if (outpoint.n < out.tx->vout.size() && wallet->IsMine(out.tx->vout[outpoint.n]) == ISMINE_SPENDABLE)
vCoins.push_back(out);
}
BOOST_FOREACH(const COutput& out, vCoins)

View file

@ -114,8 +114,6 @@ Value importprivkey(const Array& params, bool fHelp)
CPubKey pubkey = key.GetPubKey();
CKeyID vchAddress = pubkey.GetID();
{
LOCK2(cs_main, pwalletMain->cs_wallet);
pwalletMain->MarkDirty();
pwalletMain->SetAddressBook(vchAddress, strLabel, "receive");
@ -181,7 +179,8 @@ Value importaddress(const Array& params, bool fHelp)
fRescan = params[2].get_bool();
{
LOCK2(cs_main, pwalletMain->cs_wallet);
if (::IsMine(*pwalletMain, script) == ISMINE_SPENDABLE)
throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
// add to address book or update label
if (address.IsValid())

View file

@ -1539,7 +1539,7 @@ Value gettransaction(const Array& params, bool fHelp)
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
const CWalletTx& wtx = pwalletMain->mapWallet[hash];
CAmount nCredit = wtx.GetCredit(filter != 0);
CAmount nCredit = wtx.GetCredit(filter);
CAmount nDebit = wtx.GetDebit(filter);
CAmount nNet = nCredit - nDebit;
CAmount nFee = (wtx.IsFromMe(filter) ? wtx.GetValueOut() - nDebit : 0);

View file

@ -89,6 +89,13 @@ bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey)
AssertLockHeld(cs_wallet); // mapKeyMetadata
if (!CCryptoKeyStore::AddKeyPubKey(secret, pubkey))
return false;
// check if we need to remove from watch-only
CScript script;
script = GetScriptForDestination(pubkey.GetID());
if (HaveWatchOnly(script))
RemoveWatchOnly(script);
if (!fFileBacked)
return true;
if (!IsCrypted()) {
@ -171,6 +178,20 @@ bool CWallet::AddWatchOnly(const CScript &dest)
return CWalletDB(strWalletFile).WriteWatchOnly(dest);
}
bool CWallet::RemoveWatchOnly(const CScript &dest)
{
AssertLockHeld(cs_wallet);
if (!CCryptoKeyStore::RemoveWatchOnly(dest))
return false;
if (!HaveWatchOnly())
NotifyWatchonlyChanged(false);
if (fFileBacked)
if (!CWalletDB(strWalletFile).EraseWatchOnly(dest))
return false;
return true;
}
bool CWallet::LoadWatchOnly(const CScript &dest)
{
return CCryptoKeyStore::AddWatchOnly(dest);

View file

@ -230,6 +230,7 @@ public:
// Adds a watch-only address to the store, and saves it to disk.
bool AddWatchOnly(const CScript &dest);
bool RemoveWatchOnly(const CScript &dest);
// Adds a watch-only address to the store, without saving it to disk (used by LoadWallet)
bool LoadWatchOnly(const CScript &dest);
@ -709,18 +710,37 @@ public:
return debit;
}
CAmount GetCredit(bool fUseCache=true) const
CAmount GetCredit(const isminefilter& filter) const
{
// Must wait until coinbase is safely deep enough in the chain before valuing it
if (IsCoinBase() && GetBlocksToMaturity() > 0)
return 0;
// GetBalance can assume transactions in mapWallet won't change
if (fUseCache && fCreditCached)
return nCreditCached;
nCreditCached = pwallet->GetCredit(*this, ISMINE_ALL);
fCreditCached = true;
return nCreditCached;
int64_t credit = 0;
if (filter & ISMINE_SPENDABLE)
{
// GetBalance can assume transactions in mapWallet won't change
if (fCreditCached)
credit += nCreditCached;
else
{
nCreditCached = pwallet->GetCredit(*this, ISMINE_SPENDABLE);
fCreditCached = true;
credit += nCreditCached;
}
}
if (filter & ISMINE_WATCH_ONLY)
{
if (fWatchCreditCached)
credit += nWatchCreditCached;
else
{
nWatchCreditCached = pwallet->GetCredit(*this, ISMINE_WATCH_ONLY);
fWatchCreditCached = true;
credit += nWatchCreditCached;
}
}
return credit;
}
CAmount GetImmatureCredit(bool fUseCache=true) const

View file

@ -121,6 +121,12 @@ bool CWalletDB::WriteWatchOnly(const CScript &dest)
return Write(std::make_pair(std::string("watchs"), dest), '1');
}
bool CWalletDB::EraseWatchOnly(const CScript &dest)
{
nWalletDBUpdated++;
return Erase(std::make_pair(std::string("watchs"), dest));
}
bool CWalletDB::WriteBestBlock(const CBlockLocator& locator)
{
nWalletDBUpdated++;

View file

@ -96,6 +96,7 @@ public:
bool WriteCScript(const uint160& hash, const CScript& redeemScript);
bool WriteWatchOnly(const CScript &script);
bool EraseWatchOnly(const CScript &script);
bool WriteBestBlock(const CBlockLocator& locator);
bool ReadBestBlock(CBlockLocator& locator);