mirror of
https://github.com/twisterarmy/twister-core.git
synced 2025-01-23 04:54:30 +00:00
another big wallet cleanup
This commit is contained in:
parent
9946d6ed72
commit
78ba2a5609
@ -11,7 +11,6 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
class CBlockIndex;
|
class CBlockIndex;
|
||||||
class CReserveKey;
|
|
||||||
|
|
||||||
#include "json/json_spirit_reader_template.h"
|
#include "json/json_spirit_reader_template.h"
|
||||||
#include "json/json_spirit_writer_template.h"
|
#include "json/json_spirit_writer_template.h"
|
||||||
|
@ -840,12 +840,14 @@ bool AppInit2(boost::thread_group& threadGroup)
|
|||||||
// Create new keyUser and set as default key
|
// Create new keyUser and set as default key
|
||||||
RandAddSeedPerfmon();
|
RandAddSeedPerfmon();
|
||||||
|
|
||||||
|
/* [MF] FIXME: require user on initialization?
|
||||||
CPubKey newDefaultKey;
|
CPubKey newDefaultKey;
|
||||||
if (pwalletMain->GetKeyFromPool(newDefaultKey, false)) {
|
if (pwalletMain->GetKeyFromPool(newDefaultKey, false)) {
|
||||||
pwalletMain->SetDefaultKey(newDefaultKey);
|
pwalletMain->SetDefaultKey(newDefaultKey);
|
||||||
if (!pwalletMain->SetAddressBookName(pwalletMain->vchDefaultKey.GetID(), ""))
|
if (!pwalletMain->SetAddressBookName(pwalletMain->vchDefaultKey.GetID(), ""))
|
||||||
strErrors << _("Cannot write default address") << "\n";
|
strErrors << _("Cannot write default address") << "\n";
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
pwalletMain->SetBestChain(CBlockLocator(pindexBest));
|
pwalletMain->SetBestChain(CBlockLocator(pindexBest));
|
||||||
}
|
}
|
||||||
|
@ -228,9 +228,7 @@ Value dumpwallet(const Array& params, bool fHelp)
|
|||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file");
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file");
|
||||||
|
|
||||||
std::map<CKeyID, int64> mapKeyBirth;
|
std::map<CKeyID, int64> mapKeyBirth;
|
||||||
std::set<CKeyID> setKeyPool;
|
|
||||||
pwalletMain->GetKeyBirthTimes(mapKeyBirth);
|
pwalletMain->GetKeyBirthTimes(mapKeyBirth);
|
||||||
pwalletMain->GetAllReserveKeys(setKeyPool);
|
|
||||||
|
|
||||||
// sort time/key pairs
|
// sort time/key pairs
|
||||||
std::vector<std::pair<int64, CKeyID> > vKeyBirth;
|
std::vector<std::pair<int64, CKeyID> > vKeyBirth;
|
||||||
|
@ -80,9 +80,6 @@ Value getinfo(const Array& params, bool fHelp)
|
|||||||
obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string())));
|
obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string())));
|
||||||
obj.push_back(Pair("difficulty", (double)GetDifficulty()));
|
obj.push_back(Pair("difficulty", (double)GetDifficulty()));
|
||||||
obj.push_back(Pair("testnet", TestNet()));
|
obj.push_back(Pair("testnet", TestNet()));
|
||||||
obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
|
|
||||||
obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
|
|
||||||
obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
|
|
||||||
if (pwalletMain->IsCrypted())
|
if (pwalletMain->IsCrypted())
|
||||||
obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime));
|
obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime));
|
||||||
obj.push_back(Pair("errors", GetWarnings("statusbar")));
|
obj.push_back(Pair("errors", GetWarnings("statusbar")));
|
||||||
|
515
src/wallet.cpp
515
src/wallet.cpp
@ -49,6 +49,9 @@ CPubKey CWallet::GenerateNewKey(std::string username)
|
|||||||
|
|
||||||
if (!AddKeyPubKey(secret, pubkey))
|
if (!AddKeyPubKey(secret, pubkey))
|
||||||
throw std::runtime_error("CWallet::GenerateNewKey() : AddKey failed");
|
throw std::runtime_error("CWallet::GenerateNewKey() : AddKey failed");
|
||||||
|
|
||||||
|
if (!vchDefaultKey.IsValid())
|
||||||
|
vchDefaultKey = pubkey;
|
||||||
return pubkey;
|
return pubkey;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -683,253 +686,6 @@ void CWallet::ResendWalletTransactions()
|
|||||||
// Actions
|
// Actions
|
||||||
//
|
//
|
||||||
|
|
||||||
bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend,
|
|
||||||
CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet, std::string& strFailReason)
|
|
||||||
{
|
|
||||||
int64 nValue = 0;
|
|
||||||
BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
|
|
||||||
{
|
|
||||||
if (nValue < 0)
|
|
||||||
{
|
|
||||||
strFailReason = _("Transaction amounts must be positive");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
nValue += s.second;
|
|
||||||
}
|
|
||||||
if (vecSend.empty() || nValue < 0)
|
|
||||||
{
|
|
||||||
strFailReason = _("Transaction amounts must be positive");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
wtxNew.BindWallet(this);
|
|
||||||
|
|
||||||
{
|
|
||||||
LOCK2(cs_main, cs_wallet);
|
|
||||||
{
|
|
||||||
nFeeRet = nTransactionFee;
|
|
||||||
/*
|
|
||||||
loop
|
|
||||||
{
|
|
||||||
wtxNew.vin.clear();
|
|
||||||
wtxNew.vout.clear();
|
|
||||||
wtxNew.fFromMe = true;
|
|
||||||
|
|
||||||
int64 nTotalValue = nValue + nFeeRet;
|
|
||||||
double dPriority = 0;
|
|
||||||
// vouts to the payees
|
|
||||||
BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
|
|
||||||
{
|
|
||||||
CTxOut txout(s.second, s.first);
|
|
||||||
if (txout.IsDust(CTransaction::nMinRelayTxFee))
|
|
||||||
{
|
|
||||||
strFailReason = _("Transaction amount too small");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
wtxNew.vout.push_back(txout);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Choose coins to use
|
|
||||||
set<pair<const CWalletTx*,unsigned int> > setCoins;
|
|
||||||
int64 nValueIn = 0;
|
|
||||||
if (!SelectCoins(nTotalValue, setCoins, nValueIn))
|
|
||||||
{
|
|
||||||
strFailReason = _("Insufficient funds");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
|
|
||||||
{
|
|
||||||
int64 nCredit = pcoin.first->vout[pcoin.second].nValue;
|
|
||||||
//The priority after the next block (depth+1) is used instead of the current,
|
|
||||||
//reflecting an assumption the user would accept a bit more delay for
|
|
||||||
//a chance at a free transaction.
|
|
||||||
dPriority += (double)nCredit * (pcoin.first->GetDepthInMainChain()+1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int64 nChange = nValueIn - nValue - nFeeRet;
|
|
||||||
// if sub-cent change is required, the fee must be raised to at least nMinTxFee
|
|
||||||
// or until nChange becomes zero
|
|
||||||
// NOTE: this depends on the exact behaviour of GetMinFee
|
|
||||||
if (nFeeRet < CTransaction::nMinTxFee && nChange > 0 && nChange < CENT)
|
|
||||||
{
|
|
||||||
int64 nMoveToFee = min(nChange, CTransaction::nMinTxFee - nFeeRet);
|
|
||||||
nChange -= nMoveToFee;
|
|
||||||
nFeeRet += nMoveToFee;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nChange > 0)
|
|
||||||
{
|
|
||||||
// Note: We use a new key here to keep it from being obvious which side is the change.
|
|
||||||
// The drawback is that by not reusing a previous key, the change may be lost if a
|
|
||||||
// backup is restored, if the backup doesn't have the new private key for the change.
|
|
||||||
// If we reused the old key, it would be possible to add code to look for and
|
|
||||||
// rediscover unknown transactions that were written with keys of ours to recover
|
|
||||||
// post-backup change.
|
|
||||||
|
|
||||||
// Reserve a new key pair from key pool
|
|
||||||
CPubKey vchPubKey;
|
|
||||||
assert(reservekey.GetReservedKey(vchPubKey)); // should never fail, as we just unlocked
|
|
||||||
|
|
||||||
// Fill a vout to ourself
|
|
||||||
// TODO: pass in scriptChange instead of reservekey so
|
|
||||||
// change transaction isn't always pay-to-bitcoin-address
|
|
||||||
CScript scriptChange;
|
|
||||||
scriptChange.SetDestination(vchPubKey.GetID());
|
|
||||||
|
|
||||||
CTxOut newTxOut(nChange, scriptChange);
|
|
||||||
|
|
||||||
// Never create dust outputs; if we would, just
|
|
||||||
// add the dust to the fee.
|
|
||||||
if (newTxOut.IsDust(CTransaction::nMinRelayTxFee))
|
|
||||||
{
|
|
||||||
nFeeRet += nChange;
|
|
||||||
reservekey.ReturnKey();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Insert change txn at random position:
|
|
||||||
vector<CTxOut>::iterator position = wtxNew.vout.begin()+GetRandInt(wtxNew.vout.size()+1);
|
|
||||||
wtxNew.vout.insert(position, newTxOut);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
reservekey.ReturnKey();
|
|
||||||
|
|
||||||
// Fill vin
|
|
||||||
BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
|
|
||||||
wtxNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second));
|
|
||||||
|
|
||||||
// Sign
|
|
||||||
int nIn = 0;
|
|
||||||
BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
|
|
||||||
if (!SignSignature(*this, *coin.first, wtxNew, nIn++))
|
|
||||||
{
|
|
||||||
strFailReason = _("Signing transaction failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Limit size
|
|
||||||
unsigned int nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK, PROTOCOL_VERSION);
|
|
||||||
if (nBytes >= MAX_STANDARD_TX_SIZE)
|
|
||||||
{
|
|
||||||
strFailReason = _("Transaction too large");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
dPriority /= nBytes;
|
|
||||||
|
|
||||||
// Check that enough fee is included
|
|
||||||
int64 nPayFee = nTransactionFee * (1 + (int64)nBytes / 1000);
|
|
||||||
bool fAllowFree = AllowFree(dPriority);
|
|
||||||
int64 nMinFee = GetMinFee(wtxNew, fAllowFree, GMF_SEND);
|
|
||||||
if (nFeeRet < max(nPayFee, nMinFee))
|
|
||||||
{
|
|
||||||
nFeeRet = max(nPayFee, nMinFee);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fill vtxPrev by copying from previous transactions vtxPrev
|
|
||||||
wtxNew.AddSupportingTransactions();
|
|
||||||
wtxNew.fTimeReceivedIsTxTime = true;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CWallet::CreateTransaction(CScript scriptPubKey, int64 nValue,
|
|
||||||
CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet, std::string& strFailReason)
|
|
||||||
{
|
|
||||||
vector< pair<CScript, int64> > vecSend;
|
|
||||||
vecSend.push_back(make_pair(scriptPubKey, nValue));
|
|
||||||
return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet, strFailReason);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call after CreateTransaction unless you want to abort
|
|
||||||
bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
LOCK2(cs_main, cs_wallet);
|
|
||||||
printf("CommitTransaction:\n%s", wtxNew.ToString().c_str());
|
|
||||||
{
|
|
||||||
// This is only to keep the database open to defeat the auto-flush for the
|
|
||||||
// duration of this scope. This is the only place where this optimization
|
|
||||||
// maybe makes sense; please don't do it anywhere else.
|
|
||||||
CWalletDB* pwalletdb = fFileBacked ? new CWalletDB(strWalletFile,"r") : NULL;
|
|
||||||
|
|
||||||
// Take key pair from key pool so it won't be used again
|
|
||||||
reservekey.KeepKey();
|
|
||||||
|
|
||||||
// Add tx to wallet, because if it has change it's also ours,
|
|
||||||
// otherwise just for transaction history.
|
|
||||||
AddToWallet(wtxNew);
|
|
||||||
|
|
||||||
// Mark old coins as spent
|
|
||||||
set<CWalletTx*> setCoins;
|
|
||||||
/*
|
|
||||||
BOOST_FOREACH(const CTxIn& txin, wtxNew.vin)
|
|
||||||
{
|
|
||||||
CWalletTx &coin = mapWallet[txin.prevout.hash];
|
|
||||||
coin.BindWallet(this);
|
|
||||||
coin.MarkSpent(txin.prevout.n);
|
|
||||||
coin.WriteToDisk();
|
|
||||||
NotifyTransactionChanged(this, coin.GetHash(), CT_UPDATED);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (fFileBacked)
|
|
||||||
delete pwalletdb;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Track how many getdata requests our transaction gets
|
|
||||||
mapRequestCount[wtxNew.GetHash()] = 0;
|
|
||||||
|
|
||||||
// Broadcast
|
|
||||||
if (!wtxNew.AcceptToMemoryPool(false))
|
|
||||||
{
|
|
||||||
// This must not fail. The transaction has already been signed and recorded.
|
|
||||||
printf("CommitTransaction() : Error: Transaction not valid");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
wtxNew.RelayWalletTransaction();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
|
|
||||||
{
|
|
||||||
CReserveKey reservekey(this);
|
|
||||||
int64 nFeeRequired;
|
|
||||||
|
|
||||||
if (IsLocked())
|
|
||||||
{
|
|
||||||
string strError = _("Error: Wallet locked, unable to create transaction!");
|
|
||||||
printf("SendMoney() : %s", strError.c_str());
|
|
||||||
return strError;
|
|
||||||
}
|
|
||||||
string strError;
|
|
||||||
if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired, strError))
|
|
||||||
{
|
|
||||||
printf("SendMoney() : %s\n", strError.c_str());
|
|
||||||
return strError;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fAskFee && !uiInterface.ThreadSafeAskFee(nFeeRequired))
|
|
||||||
return "ABORTED";
|
|
||||||
|
|
||||||
if (!CommitTransaction(wtxNew, reservekey))
|
|
||||||
return _("Error: The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.");
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
|
DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
|
||||||
{
|
{
|
||||||
if (!fFileBacked)
|
if (!fFileBacked)
|
||||||
@ -955,24 +711,6 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool CWallet::SetAddressBookName(const CTxDestination& address, const string& strName)
|
|
||||||
{
|
|
||||||
std::map<CTxDestination, std::string>::iterator mi = mapAddressBook.find(address);
|
|
||||||
mapAddressBook[address] = strName;
|
|
||||||
NotifyAddressBookChanged(this, address, strName, ::IsMine(*this, address), (mi == mapAddressBook.end()) ? CT_NEW : CT_UPDATED);
|
|
||||||
if (!fFileBacked)
|
|
||||||
return false;
|
|
||||||
return CWalletDB(strWalletFile).WriteName(CBitcoinAddress(address).ToString(), strName);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CWallet::DelAddressBookName(const CTxDestination& address)
|
|
||||||
{
|
|
||||||
mapAddressBook.erase(address);
|
|
||||||
NotifyAddressBookChanged(this, address, "", ::IsMine(*this, address), CT_DELETED);
|
|
||||||
if (!fFileBacked)
|
|
||||||
return false;
|
|
||||||
return CWalletDB(strWalletFile).EraseName(CBitcoinAddress(address).ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool CWallet::SetDefaultKey(const CPubKey &vchPubKey)
|
bool CWallet::SetDefaultKey(const CPubKey &vchPubKey)
|
||||||
@ -995,253 +733,6 @@ bool GetWalletFile(CWallet* pwallet, string &strWalletFileOut)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
|
|
||||||
{
|
|
||||||
nIndex = -1;
|
|
||||||
keypool.vchPubKey = CPubKey();
|
|
||||||
{
|
|
||||||
LOCK(cs_wallet);
|
|
||||||
|
|
||||||
// Get the oldest key
|
|
||||||
if(setKeyPool.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
CWalletDB walletdb(strWalletFile);
|
|
||||||
|
|
||||||
nIndex = *(setKeyPool.begin());
|
|
||||||
setKeyPool.erase(setKeyPool.begin());
|
|
||||||
if (!walletdb.ReadPool(nIndex, keypool))
|
|
||||||
throw runtime_error("ReserveKeyFromKeyPool() : read failed");
|
|
||||||
if (!HaveKey(keypool.vchPubKey.GetID()))
|
|
||||||
throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool");
|
|
||||||
assert(keypool.vchPubKey.IsValid());
|
|
||||||
printf("keypool reserve %"PRI64d"\n", nIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int64 CWallet::AddReserveKey(const CKeyPool& keypool)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
LOCK2(cs_main, cs_wallet);
|
|
||||||
CWalletDB walletdb(strWalletFile);
|
|
||||||
|
|
||||||
int64 nIndex = 1 + *(--setKeyPool.end());
|
|
||||||
if (!walletdb.WritePool(nIndex, keypool))
|
|
||||||
throw runtime_error("AddReserveKey() : writing added key failed");
|
|
||||||
setKeyPool.insert(nIndex);
|
|
||||||
return nIndex;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWallet::KeepKey(int64 nIndex)
|
|
||||||
{
|
|
||||||
// Remove from key pool
|
|
||||||
if (fFileBacked)
|
|
||||||
{
|
|
||||||
CWalletDB walletdb(strWalletFile);
|
|
||||||
walletdb.ErasePool(nIndex);
|
|
||||||
}
|
|
||||||
printf("keypool keep %"PRI64d"\n", nIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWallet::ReturnKey(int64 nIndex)
|
|
||||||
{
|
|
||||||
// Return to key pool
|
|
||||||
{
|
|
||||||
LOCK(cs_wallet);
|
|
||||||
setKeyPool.insert(nIndex);
|
|
||||||
}
|
|
||||||
printf("keypool return %"PRI64d"\n", nIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CWallet::GetKeyFromPool(CPubKey& result, bool fAllowReuse)
|
|
||||||
{
|
|
||||||
/* [MF] pool is going to die.
|
|
||||||
int64 nIndex = 0;
|
|
||||||
CKeyPool keypool;
|
|
||||||
{
|
|
||||||
LOCK(cs_wallet);
|
|
||||||
ReserveKeyFromKeyPool(nIndex, keypool);
|
|
||||||
if (nIndex == -1)
|
|
||||||
{
|
|
||||||
if (fAllowReuse && vchDefaultKey.IsValid())
|
|
||||||
{
|
|
||||||
result = vchDefaultKey;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (IsLocked()) return false;
|
|
||||||
result = GenerateNewKey();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
KeepKey(nIndex);
|
|
||||||
result = keypool.vchPubKey;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
*/
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64 CWallet::GetOldestKeyPoolTime()
|
|
||||||
{
|
|
||||||
int64 nIndex = 0;
|
|
||||||
CKeyPool keypool;
|
|
||||||
ReserveKeyFromKeyPool(nIndex, keypool);
|
|
||||||
if (nIndex == -1)
|
|
||||||
return GetTime();
|
|
||||||
ReturnKey(nIndex);
|
|
||||||
return keypool.nTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
set< set<CTxDestination> > CWallet::GetAddressGroupings()
|
|
||||||
{
|
|
||||||
set< set<CTxDestination> > groupings;
|
|
||||||
set<CTxDestination> grouping;
|
|
||||||
|
|
||||||
BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet)
|
|
||||||
{
|
|
||||||
CWalletTx *pcoin = &walletEntry.second;
|
|
||||||
/*
|
|
||||||
if (pcoin->vin.size() > 0)
|
|
||||||
{
|
|
||||||
bool any_mine = false;
|
|
||||||
// group all input addresses with each other
|
|
||||||
BOOST_FOREACH(CTxIn txin, pcoin->vin)
|
|
||||||
{
|
|
||||||
CTxDestination address;
|
|
||||||
if(!IsMine(txin))
|
|
||||||
continue;
|
|
||||||
if(!ExtractDestination(mapWallet[txin.prevout.hash].vout[txin.prevout.n].scriptPubKey, address))
|
|
||||||
continue;
|
|
||||||
grouping.insert(address);
|
|
||||||
any_mine = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// group change with input addresses
|
|
||||||
if (any_mine)
|
|
||||||
{
|
|
||||||
BOOST_FOREACH(CTxOut txout, pcoin->vout)
|
|
||||||
if (IsChange(txout))
|
|
||||||
{
|
|
||||||
CTxDestination txoutAddr;
|
|
||||||
if(!ExtractDestination(txout.scriptPubKey, txoutAddr))
|
|
||||||
continue;
|
|
||||||
grouping.insert(txoutAddr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (grouping.size() > 0)
|
|
||||||
{
|
|
||||||
groupings.insert(grouping);
|
|
||||||
grouping.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// group lone addrs by themselves
|
|
||||||
for (unsigned int i = 0; i < pcoin->vout.size(); i++)
|
|
||||||
if (IsMine(pcoin->vout[i]))
|
|
||||||
{
|
|
||||||
CTxDestination address;
|
|
||||||
if(!ExtractDestination(pcoin->vout[i].scriptPubKey, address))
|
|
||||||
continue;
|
|
||||||
grouping.insert(address);
|
|
||||||
groupings.insert(grouping);
|
|
||||||
grouping.clear();
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
set< set<CTxDestination>* > uniqueGroupings; // a set of pointers to groups of addresses
|
|
||||||
map< CTxDestination, set<CTxDestination>* > setmap; // map addresses to the unique group containing it
|
|
||||||
BOOST_FOREACH(set<CTxDestination> grouping, groupings)
|
|
||||||
{
|
|
||||||
// make a set of all the groups hit by this new group
|
|
||||||
set< set<CTxDestination>* > hits;
|
|
||||||
map< CTxDestination, set<CTxDestination>* >::iterator it;
|
|
||||||
BOOST_FOREACH(CTxDestination address, grouping)
|
|
||||||
if ((it = setmap.find(address)) != setmap.end())
|
|
||||||
hits.insert((*it).second);
|
|
||||||
|
|
||||||
// merge all hit groups into a new single group and delete old groups
|
|
||||||
set<CTxDestination>* merged = new set<CTxDestination>(grouping);
|
|
||||||
BOOST_FOREACH(set<CTxDestination>* hit, hits)
|
|
||||||
{
|
|
||||||
merged->insert(hit->begin(), hit->end());
|
|
||||||
uniqueGroupings.erase(hit);
|
|
||||||
delete hit;
|
|
||||||
}
|
|
||||||
uniqueGroupings.insert(merged);
|
|
||||||
|
|
||||||
// update setmap
|
|
||||||
BOOST_FOREACH(CTxDestination element, *merged)
|
|
||||||
setmap[element] = merged;
|
|
||||||
}
|
|
||||||
|
|
||||||
set< set<CTxDestination> > ret;
|
|
||||||
BOOST_FOREACH(set<CTxDestination>* uniqueGrouping, uniqueGroupings)
|
|
||||||
{
|
|
||||||
ret.insert(*uniqueGrouping);
|
|
||||||
delete uniqueGrouping;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CReserveKey::GetReservedKey(CPubKey& pubkey)
|
|
||||||
{
|
|
||||||
if (nIndex == -1)
|
|
||||||
{
|
|
||||||
CKeyPool keypool;
|
|
||||||
pwallet->ReserveKeyFromKeyPool(nIndex, keypool);
|
|
||||||
if (nIndex != -1)
|
|
||||||
vchPubKey = keypool.vchPubKey;
|
|
||||||
else {
|
|
||||||
if (pwallet->vchDefaultKey.IsValid()) {
|
|
||||||
printf("CReserveKey::GetReservedKey(): Warning: Using default key instead of a new key, top up your keypool!");
|
|
||||||
vchPubKey = pwallet->vchDefaultKey;
|
|
||||||
} else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert(vchPubKey.IsValid());
|
|
||||||
pubkey = vchPubKey;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CReserveKey::KeepKey()
|
|
||||||
{
|
|
||||||
if (nIndex != -1)
|
|
||||||
pwallet->KeepKey(nIndex);
|
|
||||||
nIndex = -1;
|
|
||||||
vchPubKey = CPubKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CReserveKey::ReturnKey()
|
|
||||||
{
|
|
||||||
if (nIndex != -1)
|
|
||||||
pwallet->ReturnKey(nIndex);
|
|
||||||
nIndex = -1;
|
|
||||||
vchPubKey = CPubKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWallet::GetAllReserveKeys(set<CKeyID>& setAddress) const
|
|
||||||
{
|
|
||||||
setAddress.clear();
|
|
||||||
|
|
||||||
CWalletDB walletdb(strWalletFile);
|
|
||||||
|
|
||||||
LOCK2(cs_main, cs_wallet);
|
|
||||||
BOOST_FOREACH(const int64& id, setKeyPool)
|
|
||||||
{
|
|
||||||
CKeyPool keypool;
|
|
||||||
if (!walletdb.ReadPool(id, keypool))
|
|
||||||
throw runtime_error("GetAllReserveKeyHashes() : read failed");
|
|
||||||
assert(keypool.vchPubKey.IsValid());
|
|
||||||
CKeyID keyID = keypool.vchPubKey.GetID();
|
|
||||||
if (!HaveKey(keyID))
|
|
||||||
throw runtime_error("GetAllReserveKeyHashes() : unknown key in key pool");
|
|
||||||
setAddress.insert(keyID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWallet::UpdatedTransaction(const uint256 &hashTx)
|
void CWallet::UpdatedTransaction(const uint256 &hashTx)
|
||||||
{
|
{
|
||||||
|
50
src/wallet.h
50
src/wallet.h
@ -20,7 +20,6 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
class CWalletTx;
|
class CWalletTx;
|
||||||
class CReserveKey;
|
|
||||||
class COutput;
|
class COutput;
|
||||||
class CWalletDB;
|
class CWalletDB;
|
||||||
|
|
||||||
@ -160,22 +159,6 @@ public:
|
|||||||
int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false);
|
int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false);
|
||||||
void ReacceptWalletTransactions();
|
void ReacceptWalletTransactions();
|
||||||
void ResendWalletTransactions();
|
void ResendWalletTransactions();
|
||||||
bool CreateTransaction(const std::vector<std::pair<CScript, int64> >& vecSend,
|
|
||||||
CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet, std::string& strFailReason);
|
|
||||||
bool CreateTransaction(CScript scriptPubKey, int64 nValue,
|
|
||||||
CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet, std::string& strFailReason);
|
|
||||||
bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey);
|
|
||||||
std::string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
|
|
||||||
|
|
||||||
int64 AddReserveKey(const CKeyPool& keypool);
|
|
||||||
void ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool);
|
|
||||||
void KeepKey(int64 nIndex);
|
|
||||||
void ReturnKey(int64 nIndex);
|
|
||||||
bool GetKeyFromPool(CPubKey &key, bool fAllowReuse=true);
|
|
||||||
int64 GetOldestKeyPoolTime();
|
|
||||||
void GetAllReserveKeys(std::set<CKeyID>& setAddress) const;
|
|
||||||
|
|
||||||
std::set< std::set<CTxDestination> > GetAddressGroupings();
|
|
||||||
|
|
||||||
bool IsMine(const CTransaction& tx) const
|
bool IsMine(const CTransaction& tx) const
|
||||||
{
|
{
|
||||||
@ -189,10 +172,6 @@ public:
|
|||||||
|
|
||||||
DBErrors LoadWallet(bool& fFirstRunRet);
|
DBErrors LoadWallet(bool& fFirstRunRet);
|
||||||
|
|
||||||
bool SetAddressBookName(const CTxDestination& address, const std::string& strName);
|
|
||||||
|
|
||||||
bool DelAddressBookName(const CTxDestination& address);
|
|
||||||
|
|
||||||
void UpdatedTransaction(const uint256 &hashTx);
|
void UpdatedTransaction(const uint256 &hashTx);
|
||||||
|
|
||||||
void PrintWallet(const CBlock& block);
|
void PrintWallet(const CBlock& block);
|
||||||
@ -207,11 +186,6 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetKeyPoolSize()
|
|
||||||
{
|
|
||||||
return setKeyPool.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GetTransaction(const uint256 &hashTx, CWalletTx& wtx);
|
bool GetTransaction(const uint256 &hashTx, CWalletTx& wtx);
|
||||||
|
|
||||||
bool SetDefaultKey(const CPubKey &vchPubKey);
|
bool SetDefaultKey(const CPubKey &vchPubKey);
|
||||||
@ -236,30 +210,6 @@ public:
|
|||||||
boost::signals2::signal<void (CWallet *wallet, const uint256 &hashTx, ChangeType status)> NotifyTransactionChanged;
|
boost::signals2::signal<void (CWallet *wallet, const uint256 &hashTx, ChangeType status)> NotifyTransactionChanged;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** A key allocated from the key pool. */
|
|
||||||
class CReserveKey
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
CWallet* pwallet;
|
|
||||||
int64 nIndex;
|
|
||||||
CPubKey vchPubKey;
|
|
||||||
public:
|
|
||||||
CReserveKey(CWallet* pwalletIn)
|
|
||||||
{
|
|
||||||
nIndex = -1;
|
|
||||||
pwallet = pwalletIn;
|
|
||||||
}
|
|
||||||
|
|
||||||
~CReserveKey()
|
|
||||||
{
|
|
||||||
ReturnKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ReturnKey();
|
|
||||||
bool GetReservedKey(CPubKey &pubkey);
|
|
||||||
void KeepKey();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
typedef std::map<std::string, std::string> mapValue_t;
|
typedef std::map<std::string, std::string> mapValue_t;
|
||||||
|
|
||||||
|
@ -11,8 +11,6 @@ using namespace std;
|
|||||||
using namespace boost;
|
using namespace boost;
|
||||||
|
|
||||||
|
|
||||||
static uint64 nAccountingEntryNumber = 0;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// CWalletDB
|
// CWalletDB
|
||||||
//
|
//
|
||||||
|
Loading…
x
Reference in New Issue
Block a user