[Wallet] Watch-only fixes

This commit is contained in:
Cozz Lovan 2014-07-26 21:05:11 +02:00
parent 29f96e8bc6
commit ccca27a788
10 changed files with 70 additions and 13 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -114,8 +114,6 @@ Value importprivkey(const Array& params, bool fHelp)
CPubKey pubkey = key.GetPubKey(); CPubKey pubkey = key.GetPubKey();
CKeyID vchAddress = pubkey.GetID(); CKeyID vchAddress = pubkey.GetID();
{ {
LOCK2(cs_main, pwalletMain->cs_wallet);
pwalletMain->MarkDirty(); pwalletMain->MarkDirty();
pwalletMain->SetAddressBook(vchAddress, strLabel, "receive"); pwalletMain->SetAddressBook(vchAddress, strLabel, "receive");
@ -181,7 +179,8 @@ Value importaddress(const Array& params, bool fHelp)
fRescan = params[2].get_bool(); 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 // add to address book or update label
if (address.IsValid()) 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"); throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
const CWalletTx& wtx = pwalletMain->mapWallet[hash]; const CWalletTx& wtx = pwalletMain->mapWallet[hash];
CAmount nCredit = wtx.GetCredit(filter != 0); CAmount nCredit = wtx.GetCredit(filter);
CAmount nDebit = wtx.GetDebit(filter); CAmount nDebit = wtx.GetDebit(filter);
CAmount nNet = nCredit - nDebit; CAmount nNet = nCredit - nDebit;
CAmount nFee = (wtx.IsFromMe(filter) ? wtx.GetValueOut() - nDebit : 0); CAmount nFee = (wtx.IsFromMe(filter) ? wtx.GetValueOut() - nDebit : 0);

View File

@ -87,6 +87,13 @@ bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey)
AssertLockHeld(cs_wallet); // mapKeyMetadata AssertLockHeld(cs_wallet); // mapKeyMetadata
if (!CCryptoKeyStore::AddKeyPubKey(secret, pubkey)) if (!CCryptoKeyStore::AddKeyPubKey(secret, pubkey))
return false; return false;
// check if we need to remove from watch-only
CScript script;
script = GetScriptForDestination(pubkey.GetID());
if (HaveWatchOnly(script))
RemoveWatchOnly(script);
if (!fFileBacked) if (!fFileBacked)
return true; return true;
if (!IsCrypted()) { if (!IsCrypted()) {
@ -169,6 +176,20 @@ bool CWallet::AddWatchOnly(const CScript &dest)
return CWalletDB(strWalletFile).WriteWatchOnly(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) bool CWallet::LoadWatchOnly(const CScript &dest)
{ {
return CCryptoKeyStore::AddWatchOnly(dest); return CCryptoKeyStore::AddWatchOnly(dest);

View File

@ -222,6 +222,7 @@ public:
// Adds a watch-only address to the store, and saves it to disk. // Adds a watch-only address to the store, and saves it to disk.
bool AddWatchOnly(const CScript &dest); 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) // Adds a watch-only address to the store, without saving it to disk (used by LoadWallet)
bool LoadWatchOnly(const CScript &dest); bool LoadWatchOnly(const CScript &dest);
@ -701,18 +702,37 @@ public:
return debit; 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 // Must wait until coinbase is safely deep enough in the chain before valuing it
if (IsCoinBase() && GetBlocksToMaturity() > 0) if (IsCoinBase() && GetBlocksToMaturity() > 0)
return 0; return 0;
int64_t credit = 0;
if (filter & ISMINE_SPENDABLE)
{
// GetBalance can assume transactions in mapWallet won't change // GetBalance can assume transactions in mapWallet won't change
if (fUseCache && fCreditCached) if (fCreditCached)
return nCreditCached; credit += nCreditCached;
nCreditCached = pwallet->GetCredit(*this, ISMINE_ALL); else
{
nCreditCached = pwallet->GetCredit(*this, ISMINE_SPENDABLE);
fCreditCached = true; fCreditCached = true;
return nCreditCached; 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 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'); 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) bool CWalletDB::WriteBestBlock(const CBlockLocator& locator)
{ {
nWalletDBUpdated++; nWalletDBUpdated++;

View File

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