mirror of
https://github.com/kvazar-network/kevacoin.git
synced 2025-01-23 05:14:19 +00:00
ReacceptWalletTransactions bugfix
Fix two bugs that can happen if you copy your wallet to another machine and perform transactions on both. First, ReacceptWalletTransactions would notice if the other wallet spent coins, and would correctly mark the receiving transaction spent. However, it did not add the spending transaction to the wallet. Now it does. Second, account balances could get out of sync with 'getbalance' because coins received by the other copy of the wallet were not necessarily detected. Now ReacceptWalletTransactions will scan the entire blockchain for transactions that should be in the wallet if it runs across a 'spent in the other wallet' transaction. Finally, there was a small bug in the accounts getbalance code-- generated coins with between 100 and 119 confirmations were not being counted in the balance of account "".
This commit is contained in:
parent
c9f70b381d
commit
1d23c74361
73
main.cpp
73
main.cpp
@ -187,6 +187,19 @@ bool AddToWalletIfMine(const CTransaction& tx, const CBlock* pblock)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AddToWalletIfFromMe(const CTransaction& tx, const CBlock* pblock)
|
||||||
|
{
|
||||||
|
if (tx.IsFromMe() || mapWallet.count(tx.GetHash()))
|
||||||
|
{
|
||||||
|
CWalletTx wtx(tx);
|
||||||
|
// Get merkle branch if transaction was found in a block
|
||||||
|
if (pblock)
|
||||||
|
wtx.SetMerkleBranch(pblock);
|
||||||
|
return AddToWallet(wtx);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool EraseFromWallet(uint256 hash)
|
bool EraseFromWallet(uint256 hash)
|
||||||
{
|
{
|
||||||
CRITICAL_BLOCK(cs_mapWallet)
|
CRITICAL_BLOCK(cs_mapWallet)
|
||||||
@ -404,7 +417,7 @@ void CWalletTx::GetAmounts(int64& nGenerated, list<pair<string, int64> >& listRe
|
|||||||
|
|
||||||
if (IsCoinBase())
|
if (IsCoinBase())
|
||||||
{
|
{
|
||||||
if (GetBlocksToMaturity() == 0)
|
if (GetDepthInMainChain() >= COINBASE_MATURITY)
|
||||||
nGenerated = GetCredit();
|
nGenerated = GetCredit();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -849,11 +862,50 @@ bool CWalletTx::AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ScanForWalletTransactions(CBlockIndex* pindexStart)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
CBlockIndex* pindex = pindexStart;
|
||||||
|
CRITICAL_BLOCK(cs_mapWallet)
|
||||||
|
{
|
||||||
|
while (pindex)
|
||||||
|
{
|
||||||
|
CBlock block;
|
||||||
|
block.ReadFromDisk(pindex, true);
|
||||||
|
foreach(CTransaction& tx, block.vtx)
|
||||||
|
{
|
||||||
|
uint256 hash = tx.GetHash();
|
||||||
|
if (mapWallet.count(hash)) continue;
|
||||||
|
AddToWalletIfMine(tx, &block);
|
||||||
|
if (mapWallet.count(hash))
|
||||||
|
{
|
||||||
|
++ret;
|
||||||
|
printf("Added missing RECEIVE %s\n", hash.ToString().c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
AddToWalletIfFromMe(tx, &block);
|
||||||
|
if (mapWallet.count(hash))
|
||||||
|
{
|
||||||
|
++ret;
|
||||||
|
printf("Added missing SEND %s\n", hash.ToString().c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pindex = pindex->pnext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void ReacceptWalletTransactions()
|
void ReacceptWalletTransactions()
|
||||||
{
|
{
|
||||||
CTxDB txdb("r");
|
CTxDB txdb("r");
|
||||||
CRITICAL_BLOCK(cs_mapWallet)
|
bool fRepeat = true;
|
||||||
|
while (fRepeat) CRITICAL_BLOCK(cs_mapWallet)
|
||||||
{
|
{
|
||||||
|
fRepeat = false;
|
||||||
|
vector<CDiskTxPos> vMissingTx;
|
||||||
foreach(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
|
foreach(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
|
||||||
{
|
{
|
||||||
CWalletTx& wtx = item.second;
|
CWalletTx& wtx = item.second;
|
||||||
@ -875,12 +927,15 @@ void ReacceptWalletTransactions()
|
|||||||
{
|
{
|
||||||
if (!txindex.vSpent[i].IsNull() && wtx.vout[i].IsMine())
|
if (!txindex.vSpent[i].IsNull() && wtx.vout[i].IsMine())
|
||||||
{
|
{
|
||||||
printf("ReacceptWalletTransactions found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
|
|
||||||
wtx.fSpent = true;
|
wtx.fSpent = true;
|
||||||
wtx.WriteToDisk();
|
vMissingTx.push_back(txindex.vSpent[i]);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (wtx.fSpent)
|
||||||
|
{
|
||||||
|
printf("ReacceptWalletTransactions found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
|
||||||
|
wtx.WriteToDisk();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -890,6 +945,12 @@ void ReacceptWalletTransactions()
|
|||||||
wtx.AcceptWalletTransaction(txdb, false);
|
wtx.AcceptWalletTransaction(txdb, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!vMissingTx.empty())
|
||||||
|
{
|
||||||
|
// TODO: optimize this to scan just part of the block chain?
|
||||||
|
if (ScanForWalletTransactions(pindexGenesisBlock))
|
||||||
|
fRepeat = true; // Found missing transactions: re-do Reaccept.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1361,8 +1422,6 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool Reorganize(CTxDB& txdb, CBlockIndex* pindexNew)
|
bool Reorganize(CTxDB& txdb, CBlockIndex* pindexNew)
|
||||||
{
|
{
|
||||||
printf("REORGANIZE\n");
|
printf("REORGANIZE\n");
|
||||||
|
1
main.h
1
main.h
@ -69,6 +69,7 @@ bool AddKey(const CKey& key);
|
|||||||
vector<unsigned char> GenerateNewKey();
|
vector<unsigned char> GenerateNewKey();
|
||||||
bool AddToWallet(const CWalletTx& wtxIn);
|
bool AddToWallet(const CWalletTx& wtxIn);
|
||||||
void WalletUpdateSpent(const COutPoint& prevout);
|
void WalletUpdateSpent(const COutPoint& prevout);
|
||||||
|
int ScanForWalletTransactions(CBlockIndex* pindexStart);
|
||||||
void ReacceptWalletTransactions();
|
void ReacceptWalletTransactions();
|
||||||
bool LoadBlockIndex(bool fAllowNew=true);
|
bool LoadBlockIndex(bool fAllowNew=true);
|
||||||
void PrintBlockTree();
|
void PrintBlockTree();
|
||||||
|
24
rpc.cpp
24
rpc.cpp
@ -621,6 +621,30 @@ Value getbalance(const Array& params, bool fHelp)
|
|||||||
if (params.size() == 0)
|
if (params.size() == 0)
|
||||||
return ((double)GetBalance() / (double)COIN);
|
return ((double)GetBalance() / (double)COIN);
|
||||||
|
|
||||||
|
if (params[0].get_str() == "*") {
|
||||||
|
// Calculate total balance a different way from GetBalance()
|
||||||
|
// (GetBalance() sums up all unspent TxOuts)
|
||||||
|
// getbalance and getbalance '*' should always return the same number.
|
||||||
|
int64 nBalance = 0;
|
||||||
|
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
|
||||||
|
{
|
||||||
|
const CWalletTx& wtx = (*it).second;
|
||||||
|
int64 allGenerated, allFee;
|
||||||
|
allGenerated = allFee = 0;
|
||||||
|
string strSentAccount;
|
||||||
|
list<pair<string, int64> > listReceived;
|
||||||
|
list<pair<string, int64> > listSent;
|
||||||
|
wtx.GetAmounts(allGenerated, listReceived, listSent, allFee, strSentAccount);
|
||||||
|
foreach(const PAIRTYPE(string,int64)& r, listReceived)
|
||||||
|
nBalance += r.second;
|
||||||
|
foreach(const PAIRTYPE(string,int64)& r, listSent)
|
||||||
|
nBalance -= r.second;
|
||||||
|
nBalance -= allFee;
|
||||||
|
nBalance += allGenerated;
|
||||||
|
}
|
||||||
|
return (double)nBalance / (double)COIN;
|
||||||
|
}
|
||||||
|
|
||||||
string strAccount = AccountFromValue(params[0]);
|
string strAccount = AccountFromValue(params[0]);
|
||||||
int nMinDepth = 1;
|
int nMinDepth = 1;
|
||||||
if (params.size() > 1)
|
if (params.size() > 1)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user