aboutsummaryrefslogtreecommitdiff
path: root/src/wallet
diff options
context:
space:
mode:
Diffstat (limited to 'src/wallet')
-rw-r--r--src/wallet/rpcwallet.cpp39
-rw-r--r--src/wallet/wallet.cpp78
-rw-r--r--src/wallet/wallet.h26
-rw-r--r--src/wallet/walletdb.cpp8
-rw-r--r--src/wallet/walletdb.h4
5 files changed, 87 insertions, 68 deletions
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 30b854477b..b6eaca80b3 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -835,7 +835,7 @@ UniValue movecmd(const UniValue& params, bool fHelp)
debit.nTime = nNow;
debit.strOtherAccount = strTo;
debit.strComment = strComment;
- walletdb.WriteAccountingEntry(debit);
+ pwalletMain->AddAccountingEntry(debit, walletdb);
// Credit
CAccountingEntry credit;
@@ -845,7 +845,7 @@ UniValue movecmd(const UniValue& params, bool fHelp)
credit.nTime = nNow;
credit.strOtherAccount = strFrom;
credit.strComment = strComment;
- walletdb.WriteAccountingEntry(credit);
+ pwalletMain->AddAccountingEntry(credit, walletdb);
if (!walletdb.TxnCommit())
throw JSONRPCError(RPC_DATABASE_ERROR, "database error");
@@ -1182,6 +1182,8 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts)
obj.push_back(Pair("account", strAccount));
obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
+ if (!fByAccounts)
+ obj.push_back(Pair("label", strAccount));
UniValue transactions(UniValue::VARR);
if (it != mapTally.end())
{
@@ -1235,7 +1237,8 @@ UniValue listreceivedbyaddress(const UniValue& params, bool fHelp)
" \"address\" : \"receivingaddress\", (string) The receiving address\n"
" \"account\" : \"accountname\", (string) DEPRECATED. The account of the receiving address. The default account is \"\".\n"
" \"amount\" : x.xxx, (numeric) The total amount in " + CURRENCY_UNIT + " received by the address\n"
- " \"confirmations\" : n (numeric) The number of confirmations of the most recent transaction included\n"
+ " \"confirmations\" : n, (numeric) The number of confirmations of the most recent transaction included\n"
+ " \"label\" : \"label\" (string) A comment for the address/transaction, if any\n"
" }\n"
" ,...\n"
"]\n"
@@ -1271,7 +1274,8 @@ UniValue listreceivedbyaccount(const UniValue& params, bool fHelp)
" \"involvesWatchonly\" : true, (bool) Only returned if imported addresses were involved in transaction\n"
" \"account\" : \"accountname\", (string) The account name of the receiving account\n"
" \"amount\" : x.xxx, (numeric) The total amount received by addresses with this account\n"
- " \"confirmations\" : n (numeric) The number of confirmations of the most recent transaction included\n"
+ " \"confirmations\" : n, (numeric) The number of confirmations of the most recent transaction included\n"
+ " \"label\" : \"label\" (string) A comment for the address/transaction, if any\n"
" }\n"
" ,...\n"
"]\n"
@@ -1318,6 +1322,8 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
MaybePushAddress(entry, s.destination);
entry.push_back(Pair("category", "send"));
entry.push_back(Pair("amount", ValueFromAmount(-s.amount)));
+ if (pwalletMain->mapAddressBook.count(s.destination))
+ entry.push_back(Pair("label", pwalletMain->mapAddressBook[s.destination].name));
entry.push_back(Pair("vout", s.vout));
entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
if (fLong)
@@ -1355,6 +1361,8 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
entry.push_back(Pair("category", "receive"));
}
entry.push_back(Pair("amount", ValueFromAmount(r.amount)));
+ if (pwalletMain->mapAddressBook.count(r.destination))
+ entry.push_back(Pair("label", account));
entry.push_back(Pair("vout", r.vout));
if (fLong)
WalletTxToJSON(wtx, entry);
@@ -1409,7 +1417,7 @@ UniValue listtransactions(const UniValue& params, bool fHelp)
" \"amount\": x.xxx, (numeric) The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and for the\n"
" 'move' category for moves outbound. It is positive for the 'receive' category,\n"
" and for the 'move' category for inbound funds.\n"
- " \"vout\" : n, (numeric) the vout value\n"
+ " \"vout\": n, (numeric) the vout value\n"
" \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n"
" 'send' category of transactions.\n"
" \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and \n"
@@ -1418,11 +1426,13 @@ UniValue listtransactions(const UniValue& params, bool fHelp)
" category of transactions.\n"
" \"blockindex\": n, (numeric) The block index containing the transaction. Available for 'send' and 'receive'\n"
" category of transactions.\n"
+ " \"blocktime\": xxx, (numeric) The block time in seconds since epoch (1 Jan 1970 GMT).\n"
" \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
" \"time\": xxx, (numeric) The transaction time in seconds since epoch (midnight Jan 1 1970 GMT).\n"
" \"timereceived\": xxx, (numeric) The time received in seconds since epoch (midnight Jan 1 1970 GMT). Available \n"
" for 'send' and 'receive' category of transactions.\n"
" \"comment\": \"...\", (string) If a comment is associated with the transaction.\n"
+ " \"label\": \"label\" (string) A comment for the address/transaction, if any\n"
" \"otheraccount\": \"accountname\", (string) For the 'move' category of transactions, the account the funds came \n"
" from (for receiving funds, positive amounts), or went to (for sending funds,\n"
" negative amounts).\n"
@@ -1461,11 +1471,10 @@ UniValue listtransactions(const UniValue& params, bool fHelp)
UniValue ret(UniValue::VARR);
- std::list<CAccountingEntry> acentries;
- CWallet::TxItems txOrdered = pwalletMain->OrderedTxItems(acentries, strAccount);
+ const CWallet::TxItems & txOrdered = pwalletMain->wtxOrdered;
// iterate backwards until we have nCount items to return:
- for (CWallet::TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
+ for (CWallet::TxItems::const_reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
{
CWalletTx *const pwtx = (*it).second.first;
if (pwtx != 0)
@@ -1570,8 +1579,7 @@ UniValue listaccounts(const UniValue& params, bool fHelp)
}
}
- list<CAccountingEntry> acentries;
- CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
+ const list<CAccountingEntry> & acentries = pwalletMain->laccentries;
BOOST_FOREACH(const CAccountingEntry& entry, acentries)
mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
@@ -1613,6 +1621,7 @@ UniValue listsinceblock(const UniValue& params, bool fHelp)
" \"time\": xxx, (numeric) The transaction time in seconds since epoch (Jan 1 1970 GMT).\n"
" \"timereceived\": xxx, (numeric) The time received in seconds since epoch (Jan 1 1970 GMT). Available for 'send' and 'receive' category of transactions.\n"
" \"comment\": \"...\", (string) If a comment is associated with the transaction.\n"
+ " \"label\" : \"label\" (string) A comment for the address/transaction, if any\n"
" \"to\": \"...\", (string) If a comment to is associated with the transaction.\n"
" ],\n"
" \"lastblock\": \"lastblockhash\" (string) The hash of the last block\n"
@@ -1700,7 +1709,8 @@ UniValue gettransaction(const UniValue& params, bool fHelp)
" \"account\" : \"accountname\", (string) DEPRECATED. The account name involved in the transaction, can be \"\" for the default account.\n"
" \"address\" : \"bitcoinaddress\", (string) The bitcoin address involved in the transaction\n"
" \"category\" : \"send|receive\", (string) The category, either 'send' or 'receive'\n"
- " \"amount\" : x.xxx (numeric) The amount in " + CURRENCY_UNIT + "\n"
+ " \"amount\" : x.xxx, (numeric) The amount in " + CURRENCY_UNIT + "\n"
+ " \"label\" : \"label\", (string) A comment for the address/transaction, if any\n"
" \"vout\" : n, (numeric) the vout value\n"
" }\n"
" ,...\n"
@@ -2385,7 +2395,7 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp)
"\nResult:\n"
"{\n"
" \"hex\": \"value\", (string) The resulting raw transaction (hex-encoded string)\n"
- " \"fee\": n, (numeric) The fee added to the transaction\n"
+ " \"fee\": n, (numeric) Fee the resulting transaction pays\n"
" \"changepos\": n (numeric) The position of the added change output, or -1\n"
"}\n"
"\"hex\" \n"
@@ -2407,9 +2417,12 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp)
if (!DecodeHexTx(origTx, params[0].get_str()))
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
+ if (origTx.vout.size() == 0)
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "TX must have at least one output");
+
bool includeWatching = false;
if (params.size() > 1)
- includeWatching = true;
+ includeWatching = params[1].get_bool();
CMutableTransaction tx(origTx);
CAmount nFee;
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 93c7c7f247..c5246d909e 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -588,31 +588,6 @@ int64_t CWallet::IncOrderPosNext(CWalletDB *pwalletdb)
return nRet;
}
-CWallet::TxItems CWallet::OrderedTxItems(std::list<CAccountingEntry>& acentries, std::string strAccount)
-{
- AssertLockHeld(cs_wallet); // mapWallet
- CWalletDB walletdb(strWalletFile);
-
- // First: get all CWalletTx and CAccountingEntry into a sorted-by-order multimap.
- TxItems txOrdered;
-
- // Note: maintaining indices in the database of (account,time) --> txid and (account, time) --> acentry
- // would make this much faster for applications that do this a lot.
- for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
- {
- CWalletTx* wtx = &((*it).second);
- txOrdered.insert(make_pair(wtx->nOrderPos, TxPair(wtx, (CAccountingEntry*)0)));
- }
- acentries.clear();
- walletdb.ListAccountCreditDebit(strAccount, acentries);
- BOOST_FOREACH(CAccountingEntry& entry, acentries)
- {
- txOrdered.insert(make_pair(entry.nOrderPos, TxPair((CWalletTx*)0, &entry)));
- }
-
- return txOrdered;
-}
-
void CWallet::MarkDirty()
{
{
@@ -629,7 +604,9 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletD
if (fFromLoadWallet)
{
mapWallet[hash] = wtxIn;
- mapWallet[hash].BindWallet(this);
+ CWalletTx& wtx = mapWallet[hash];
+ wtx.BindWallet(this);
+ wtxOrdered.insert(make_pair(wtx.nOrderPos, TxPair(&wtx, (CAccountingEntry*)0)));
AddToSpends(hash);
}
else
@@ -644,6 +621,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletD
{
wtx.nTimeReceived = GetAdjustedTime();
wtx.nOrderPos = IncOrderPosNext(pwalletdb);
+ wtxOrdered.insert(make_pair(wtx.nOrderPos, TxPair(&wtx, (CAccountingEntry*)0)));
wtx.nTimeSmart = wtx.nTimeReceived;
if (!wtxIn.hashBlock.IsNull())
@@ -655,9 +633,8 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletD
{
// Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future
int64_t latestTolerated = latestNow + 300;
- std::list<CAccountingEntry> acentries;
- TxItems txOrdered = OrderedTxItems(acentries);
- for (TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
+ const TxItems & txOrdered = wtxOrdered;
+ for (TxItems::const_reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
{
CWalletTx *const pwtx = (*it).second.first;
if (pwtx == &wtx)
@@ -1078,7 +1055,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
ShowProgress(_("Rescanning..."), std::max(1, std::min(99, (int)((Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), pindex, false) - dProgressStart) / (dProgressTip - dProgressStart) * 100))));
CBlock block;
- ReadBlockFromDisk(block, pindex);
+ ReadBlockFromDisk(block, pindex, Params().GetConsensus());
BOOST_FOREACH(CTransaction& tx, block.vtx)
{
if (AddToWalletIfInvolvingMe(tx, &block, fUpdate))
@@ -2033,13 +2010,9 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
if (fSendFreeTransactions && nBytes <= MAX_FREE_TRANSACTION_CREATE_SIZE)
{
// Not enough fee: enough priority?
- double dPriorityNeeded = mempool.estimatePriority(nTxConfirmTarget);
- // Not enough mempool history to estimate: use hard-coded AllowFree.
- if (dPriorityNeeded <= 0 && AllowFree(dPriority))
- break;
-
- // Small enough, and priority high enough, to send for free
- if (dPriorityNeeded > 0 && dPriority >= dPriorityNeeded)
+ double dPriorityNeeded = mempool.estimateSmartPriority(nTxConfirmTarget);
+ // Require at least hard-coded AllowFree.
+ if (dPriority >= dPriorityNeeded && AllowFree(dPriority))
break;
}
@@ -2118,6 +2091,23 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
return true;
}
+bool CWallet::AddAccountingEntry(const CAccountingEntry& acentry, CWalletDB & pwalletdb)
+{
+ if (!pwalletdb.WriteAccountingEntry_Backend(acentry))
+ return false;
+
+ laccentries.push_back(acentry);
+ CAccountingEntry & entry = laccentries.back();
+ wtxOrdered.insert(make_pair(entry.nOrderPos, TxPair((CWalletTx*)0, &entry)));
+
+ return true;
+}
+
+CAmount CWallet::GetRequiredFee(unsigned int nTxBytes)
+{
+ return std::max(minTxFee.GetFee(nTxBytes), ::minRelayTxFee.GetFee(nTxBytes));
+}
+
CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool)
{
// payTxFee is user-set "I want to pay this much"
@@ -2126,12 +2116,14 @@ CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarge
if (fPayAtLeastCustomFee && nFeeNeeded > 0 && nFeeNeeded < payTxFee.GetFeePerK())
nFeeNeeded = payTxFee.GetFeePerK();
// User didn't set: use -txconfirmtarget to estimate...
- if (nFeeNeeded == 0)
- nFeeNeeded = pool.estimateFee(nConfirmTarget).GetFee(nTxBytes);
- // ... unless we don't have enough mempool data, in which case fall
- // back to a hard-coded fee
- if (nFeeNeeded == 0)
- nFeeNeeded = minTxFee.GetFee(nTxBytes);
+ if (nFeeNeeded == 0) {
+ int estimateFoundTarget = nConfirmTarget;
+ nFeeNeeded = pool.estimateSmartFee(nConfirmTarget, &estimateFoundTarget).GetFee(nTxBytes);
+ // ... unless we don't have enough mempool data for our desired target
+ // so we make sure we're paying at least minTxFee
+ if (nFeeNeeded == 0 || (unsigned int)estimateFoundTarget > nConfirmTarget)
+ nFeeNeeded = std::max(nFeeNeeded, GetRequiredFee(nTxBytes));
+ }
// prevent user from paying a non-sense fee (like 1 satoshi): 0 < fee < minRelayFee
if (nFeeNeeded < ::minRelayTxFee.GetFee(nTxBytes))
nFeeNeeded = ::minRelayTxFee.GetFee(nTxBytes);
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 7e8dcc2914..7e846569ff 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -531,6 +531,11 @@ public:
}
std::map<uint256, CWalletTx> mapWallet;
+ std::list<CAccountingEntry> laccentries;
+
+ typedef std::pair<CWalletTx*, CAccountingEntry*> TxPair;
+ typedef std::multimap<int64_t, TxPair > TxItems;
+ TxItems wtxOrdered;
int64_t nOrderPosNext;
std::map<uint256, int> mapRequestCount;
@@ -617,16 +622,6 @@ public:
*/
int64_t IncOrderPosNext(CWalletDB *pwalletdb = NULL);
- typedef std::pair<CWalletTx*, CAccountingEntry*> TxPair;
- typedef std::multimap<int64_t, TxPair > TxItems;
-
- /**
- * Get the wallet's activity log
- * @return multimap of ordered transactions and accounting entries
- * @warning Returned pointers are *only* valid within the scope of passed acentries
- */
- TxItems OrderedTxItems(std::list<CAccountingEntry>& acentries, std::string strAccount = "");
-
void MarkDirty();
bool AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletDB* pwalletdb);
void SyncTransaction(const CTransaction& tx, const CBlock* pblock);
@@ -656,8 +651,19 @@ public:
std::string& strFailReason, const CCoinControl *coinControl = NULL, bool sign = true);
bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey);
+ bool AddAccountingEntry(const CAccountingEntry&, CWalletDB & pwalletdb);
+
static CFeeRate minTxFee;
+ /**
+ * Estimate the minimum fee considering user set parameters
+ * and the required fee
+ */
static CAmount GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool);
+ /**
+ * Return the minimum required fee taking into account the
+ * floating relay fee and user set minimum transaction fee
+ */
+ static CAmount GetRequiredFee(unsigned int nTxBytes);
bool NewKeyPool();
bool TopUpKeyPool(unsigned int kpSize = 0);
diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp
index ea8a4eb043..9ce9f53bd9 100644
--- a/src/wallet/walletdb.cpp
+++ b/src/wallet/walletdb.cpp
@@ -191,7 +191,7 @@ bool CWalletDB::WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccount
return Write(std::make_pair(std::string("acentry"), std::make_pair(acentry.strAccount, nAccEntryNum)), acentry);
}
-bool CWalletDB::WriteAccountingEntry(const CAccountingEntry& acentry)
+bool CWalletDB::WriteAccountingEntry_Backend(const CAccountingEntry& acentry)
{
return WriteAccountingEntry(++nAccountingEntryNumber, acentry);
}
@@ -709,6 +709,12 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet)
if (wss.fAnyUnordered)
result = ReorderTransactions(pwallet);
+ pwallet->laccentries.clear();
+ ListAccountCreditDebit("*", pwallet->laccentries);
+ BOOST_FOREACH(CAccountingEntry& entry, pwallet->laccentries) {
+ pwallet->wtxOrdered.insert(make_pair(entry.nOrderPos, CWallet::TxPair((CWalletTx*)0, &entry)));
+ }
+
return result;
}
diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h
index 270f826aed..3ebc05afd1 100644
--- a/src/wallet/walletdb.h
+++ b/src/wallet/walletdb.h
@@ -110,6 +110,9 @@ public:
bool WriteMinVersion(int nVersion);
+ /// This writes directly to the database, and will not update the CWallet's cached accounting entries!
+ /// Use wallet.AddAccountingEntry instead, to write *and* update its caches.
+ bool WriteAccountingEntry_Backend(const CAccountingEntry& acentry);
bool ReadAccount(const std::string& strAccount, CAccount& account);
bool WriteAccount(const std::string& strAccount, const CAccount& account);
@@ -118,7 +121,6 @@ public:
/// Erase destination data tuple from wallet database
bool EraseDestData(const std::string &address, const std::string &key);
- bool WriteAccountingEntry(const CAccountingEntry& acentry);
CAmount GetAccountCreditDebit(const std::string& strAccount);
void ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& acentries);