upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main.cpp47
-rw-r--r--src/main.h45
-rw-r--r--src/rpc.cpp441
3 files changed, 454 insertions, 79 deletions
diff --git a/src/main.cpp b/src/main.cpp
index 252911b..7b3e555 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -4907,9 +4907,17 @@ bool SelectCoins(int64 nTargetValue, set<CWalletTx*>& setCoinsRet)
4907 4907
4908 4908
4909 4909
4910bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, int64& nFeeRequiredRet) 4910// presultRet, when given, says WHY this returned false: the caller cannot work
4911// it out afterwards. "Coin selection came up short" and "the wallet could not
4912// build the transaction" are indistinguishable from the outside -- both are
4913// just `false` -- and the difference decides whether a pool defers a payment
4914// or counts it against the payment's retry budget. See WalletSendResult.
4915bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, int64& nFeeRequiredRet,
4916 WalletSendResult* presultRet)
4911{ 4917{
4912 nFeeRequiredRet = 0; 4918 nFeeRequiredRet = 0;
4919 if (presultRet)
4920 *presultRet = WALLET_SEND_FAILED;
4913 CRITICAL_BLOCK(cs_main) 4921 CRITICAL_BLOCK(cs_main)
4914 { 4922 {
4915 // txdb must be opened before the mapWallet lock 4923 // txdb must be opened before the mapWallet lock
@@ -4940,10 +4948,21 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, in
4940 // fixed this in 107d9e288. 4948 // fixed this in 107d9e288.
4941 int64 nTotalValue = nValue + nFee; 4949 int64 nTotalValue = nValue + nFee;
4942 4950
4943 // Choose coins to use 4951 // Choose coins to use.
4952 //
4953 // Failing here is a funding shortfall and nothing else: there
4954 // is not enough spendable coin for nValue plus the fee this
4955 // pass is working with. On the second and later passes that
4956 // fee is GetMinFee() of the transaction the first pass built,
4957 // so this is also how a wallet that can afford the amount but
4958 // not the 11 * CENT charged at 10,000 bytes reports itself.
4944 set<CWalletTx*> setCoins; 4959 set<CWalletTx*> setCoins;
4945 if (!SelectCoins(nTotalValue, setCoins)) 4960 if (!SelectCoins(nTotalValue, setCoins))
4961 {
4962 if (presultRet)
4963 *presultRet = WALLET_SEND_INSUFFICIENT_FUNDS;
4946 return false; 4964 return false;
4965 }
4947 int64 nValueIn = 0; 4966 int64 nValueIn = 0;
4948 foreach(CWalletTx* pcoin, setCoins) 4967 foreach(CWalletTx* pcoin, setCoins)
4949 nValueIn += pcoin->GetCredit(); 4968 nValueIn += pcoin->GetCredit();
@@ -5013,6 +5032,8 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, in
5013 } 5032 }
5014 } 5033 }
5015 } 5034 }
5035 if (presultRet)
5036 *presultRet = WALLET_SEND_OK;
5016 return true; 5037 return true;
5017} 5038}
5018 5039
@@ -5075,13 +5096,24 @@ bool CommitTransactionSpent(const CWalletTx& wtxNew)
5075 5096
5076 5097
5077 5098
5078bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew) 5099// outcomeRet reports what happened rather than only whether it worked. A
5100// caller that has to decide what a failure MEANS -- the pool payout thread --
5101// cannot reconstruct it from a balance reading afterwards, because the fee
5102// that was actually required depends on the size of a transaction that was
5103// never built. See WalletSendResult.
5104bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew,
5105 SendMoneyOutcome& outcomeRet)
5079{ 5106{
5107 outcomeRet.result = WALLET_SEND_FAILED;
5108 outcomeRet.nFeeRequired = 0;
5080 CRITICAL_BLOCK(cs_main) 5109 CRITICAL_BLOCK(cs_main)
5081 { 5110 {
5082 int64 nFeeRequired; 5111 int64 nFeeRequired;
5083 if (!CreateTransaction(scriptPubKey, nValue, wtxNew, nFeeRequired)) 5112 WalletSendResult createResult = WALLET_SEND_FAILED;
5113 if (!CreateTransaction(scriptPubKey, nValue, wtxNew, nFeeRequired, &createResult))
5084 { 5114 {
5115 outcomeRet.result = createResult;
5116 outcomeRet.nFeeRequired = nFeeRequired;
5085 string strError; 5117 string strError;
5086 if (nValue + nFeeRequired > GetBalance()) 5118 if (nValue + nFeeRequired > GetBalance())
5087 // Not an oversized transaction -- this branch is simply "the 5119 // Not an oversized transaction -- this branch is simply "the
@@ -5119,6 +5151,13 @@ bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew)
5119 } 5151 }
5120 wtxNew.RelayWalletTransaction(); 5152 wtxNew.RelayWalletTransaction();
5121 } 5153 }
5154 outcomeRet.result = WALLET_SEND_OK;
5122 MainFrameRepaint(); 5155 MainFrameRepaint();
5123 return true; 5156 return true;
5124} 5157}
5158
5159bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew)
5160{
5161 SendMoneyOutcome ignored;
5162 return SendMoney(scriptPubKey, nValue, wtxNew, ignored);
5163}
diff --git a/src/main.h b/src/main.h
index 8bb536b..382dd9c 100644
--- a/src/main.h
+++ b/src/main.h
@@ -342,9 +342,52 @@ struct WalletRecoveryAudit
342 } 342 }
343}; 343};
344WalletRecoveryAudit GetWalletRecoveryAudit(); 344WalletRecoveryAudit GetWalletRecoveryAudit();
345bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& txNew, int64& nFeeRequiredRet); 345
346// Why a send did not go through.
347//
348// The pool's payout thread has to decide, on every failed SendMoney, whether
349// the failure was the wallet's condition (wait for it to change) or a fault
350// (something is wrong with this payment). It used to guess by re-reading
351// GetBalance() afterwards and allowing a fixed CENT of headroom for the fee.
352// That cannot work: the fee here is a step function of the SERIALISED SIZE of
353// a transaction that no longer exists, and the step is from 0 to 11 * CENT at
354// 10,000 bytes -- so a one-CENT allowance is either unnecessary or an order of
355// magnitude short, never right. A pool wallet close to broke selects many
356// small inputs BECAUSE it is close to broke, which is what pushes the
357// transaction over 10 KB, so the guess is wrong exactly when the money is
358// tight.
359//
360// The wallet already knows the answer; it just did not say. SelectCoins()
361// failing is "there is not enough spendable coin to cover the amount plus
362// whatever fee this size of transaction requires", and it is the only reason
363// CreateTransaction() can fail that is about funding rather than about the
364// wallet being broken.
365enum WalletSendResult
366{
367 WALLET_SEND_OK = 0,
368 WALLET_SEND_INSUFFICIENT_FUNDS, // coin selection could not cover amount+fee
369 WALLET_SEND_FAILED // anything else: could not build, sign or accept
370};
371
372// What the wallet did with a send request. nFeeRequired is the fee the
373// transaction turned out to need, which for a failed send is what coin
374// selection was asked for on top of the amount and could not find -- 0 if it
375// never got that far.
376struct SendMoneyOutcome
377{
378 WalletSendResult result = WALLET_SEND_OK;
379 int64 nFeeRequired = 0;
380};
381
382bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& txNew, int64& nFeeRequiredRet,
383 WalletSendResult* presultRet=NULL);
346bool CommitTransactionSpent(const CWalletTx& wtxNew); 384bool CommitTransactionSpent(const CWalletTx& wtxNew);
385// The three-argument form is kept, and kept as a distinct declaration rather
386// than a defaulted argument, because gui.cpp declares SendMoney itself instead
387// of including this header.
347bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew); 388bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew);
389bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew,
390 SendMoneyOutcome& outcomeRet);
348 391
349 392
350 393
diff --git a/src/rpc.cpp b/src/rpc.cpp
index 403cb14..06de7f2 100644
--- a/src/rpc.cpp
+++ b/src/rpc.cpp
@@ -1700,8 +1700,11 @@ static void ForgetPayment(const PayingRecord& r)
1700 1700
1701 // When the last record for a round is gone the round is no longer in 1701 // When the last record for a round is gone the round is no longer in
1702 // flight, so a later flush may explode it again if the ledger still 1702 // flight, so a later flush may explode it again if the ledger still
1703 // shows recipients owed (a give-up, for instance, leaves the entry 1703 // shows recipients owed. That is the intended behaviour and it is now
1704 // standing). 1704 // the only way a stalled payment ever leaves this list: a payment that
1705 // keeps failing is retried forever rather than given up on, so its
1706 // record stays here, and the flush that would re-explode it is stopped
1707 // by PaymentInFlightLocked.
1705 bool stillInFlight = false; 1708 bool stillInFlight = false;
1706 for (const auto& e : gPaying) 1709 for (const auto& e : gPaying)
1707 if (SamePayoutRound(e.blockHeight, e.blockHash, 1710 if (SamePayoutRound(e.blockHeight, e.blockHash,
@@ -1776,9 +1779,16 @@ static void RecordPayoutTxid(const PayingRecord& r, const std::string& txid)
1776 LogPrint("payout", "[payout] block %d fully settled\n", r.blockHeight); 1779 LogPrint("payout", "[payout] block %d fully settled\n", r.blockHeight);
1777} 1780}
1778 1781
1779// Write a recipient off. Only reached after a full budget of failures that 1782// Write a recipient off.
1780// were NOT the wallet being locked or short of coin -- see the classification 1783//
1781// in PayoutThreadFn -- against a block still on the main chain. 1784// Only ever called for a state that is DECIDABLE -- currently one: the ledger
1785// names an address that is not a valid address, so no transaction paying it
1786// can be constructed by this or any other build. It is not called, and must
1787// not be, because a payment has failed some number of times. "The wallet said
1788// no N times" is not a decidable state, it is a description of how long we
1789// have been asking; a debt written off on the strength of it is a debt the
1790// operator keeps, and the arithmetic that decided WHY the wallet said no was
1791// wrong for a year (see PayoutThreadFn).
1782// 1792//
1783// The amount is removed from the entry rather than marked paid, so the money 1793// The amount is removed from the entry rather than marked paid, so the money
1784// is not reported as sent. Once nothing is left owed the entry retires. The 1794// is not reported as sent. Once nothing is left owed the entry retires. The
@@ -1810,6 +1820,60 @@ static void ForfeitPayoutRecipient(const PayingRecord& r, const std::string& rea
1810 r.address, reason); 1820 r.address, reason);
1811} 1821}
1812 1822
1823// What a failed send means for the payment's retry budget.
1824//
1825// A deferral is "the wallet's condition is temporarily wrong": wait, and do
1826// not hold it against this payment. A fault is "the wallet is funded and
1827// unlocked and still would not do it", which is worth logging loudly and
1828// retrying with backoff.
1829//
1830// This used to be decided by re-reading GetBalance() after the failure and
1831// comparing it against `amount + nTransactionFee + CENT`. Every term of that
1832// was wrong:
1833//
1834// * nTransactionFee is 0 in production. It is only ever assigned from the
1835// GUI preferences dialog (gui.cpp), which a headless pool node does not
1836// have, so the whole reserve was the CENT.
1837//
1838// * The fee the reserve is for is GetMinFee(fDiscount=true), a STEP
1839// function of the serialised size: 0 below 10,000 bytes, and
1840// (1 + bytes/1000) * CENT at or above it -- so 11 * CENT at the step.
1841// There is no required-fee value between 1 and 11 CENT. A one-CENT
1842// reserve is therefore never the right number: below the step nothing
1843// needs reserving, and at the step it is short by a factor of eleven.
1844//
1845// * A pool wallet close to broke selects many small inputs BECAUSE it is
1846// close to broke, and ~56 signed P2PKH inputs is 10 KB. The trigger and
1847// the failure are positively correlated: the guess is wrong precisely
1848// when the pool is nearly out of money.
1849//
1850// Concretely, with a balance of amount + 0.05: the pre-send gate passes,
1851// CreateTransaction builds a >10 KB transaction, the fee becomes 0.11,
1852// SelectCoins(amount + 0.11) fails, SendMoney returns false -- and the old
1853// arithmetic said (amount + 0.05) < (amount + 0.01) is false, so "funded",
1854// so a fault. The condition is stable, so it recurred every 60 s, and 1440 of
1855// them erased the debt with the coin still in the operator's wallet.
1856//
1857// So stop guessing. The wallet is asked to say what it did, and this only
1858// classifies the answer. WALLET_SEND_INSUFFICIENT_FUNDS is coin selection
1859// failing to cover amount plus whatever fee that size of transaction
1860// required, whatever that turned out to be -- no reserve to get wrong.
1861enum PayoutFailureClass {
1862 PAYOUT_FAILURE_DEFER = 0, // conditions are wrong; wait for them to change
1863 PAYOUT_FAILURE_FAULT // funded and unlocked, and it still would not go
1864};
1865
1866static PayoutFailureClass ClassifyPayoutSendFailure(WalletSendResult result,
1867 bool fWalletLocked)
1868{
1869 // A locked wallet cannot sign. Nothing about this payment is wrong.
1870 if (fWalletLocked)
1871 return PAYOUT_FAILURE_DEFER;
1872 if (result == WALLET_SEND_INSUFFICIENT_FUNDS)
1873 return PAYOUT_FAILURE_DEFER;
1874 return PAYOUT_FAILURE_FAULT;
1875}
1876
1813// Payout execution thread: works through gPaying, calls SendMoney. 1877// Payout execution thread: works through gPaying, calls SendMoney.
1814// Runs independently of the event loop so slow wallet operations 1878// Runs independently of the event loop so slow wallet operations
1815// (SendMoney takes cs_main) never stall miner I/O. 1879// (SendMoney takes cs_main) never stall miner I/O.
@@ -1867,9 +1931,24 @@ static void PayoutThreadFn(void*)
1867 1931
1868 uint160 h160; 1932 uint160 h160;
1869 if (!AddressToHash160(r.address, h160)) { 1933 if (!AddressToHash160(r.address, h160)) {
1870 // Should not happen -- bad addresses are filtered in QueuePayouts 1934 // Should not happen -- bad addresses are filtered in
1871 LogPrint("payout", "[payout] SKIPPED bad address '%s'\n", 1935 // QueuePayouts. If one is here anyway it is decidable and
1872 r.address.c_str()); 1936 // permanent: there is no transaction that pays a string which
1937 // is not an address, so retrying is not waiting for anything.
1938 //
1939 // This used to only ForgetPayment(), which drops the in-flight
1940 // record and leaves the ledger entry claiming the debt and
1941 // pool_rounds.json advertising the recipient as unpaid
1942 // forever, with the next flush re-exploding it. Write it off
1943 // properly and say why.
1944 const std::string reason =
1945 strprintf("'%s' is not a valid address, so no transaction"
1946 " can pay it", r.address.c_str());
1947 LogPrint("payout", "[payout] SKIPPED bad address '%s' --"
1948 " %s owed for block %d cannot be paid\n",
1949 r.address.c_str(), FormatMoney(r.amount).c_str(),
1950 r.blockHeight);
1951 ForfeitPayoutRecipient(r, reason);
1873 ForgetPayment(r); 1952 ForgetPayment(r);
1874 continue; 1953 continue;
1875 } 1954 }
@@ -1926,13 +2005,17 @@ static void PayoutThreadFn(void*)
1926 // the operator's wallet and nothing on disk saying it was owed. 2005 // the operator's wallet and nothing on disk saying it was owed.
1927 // 2006 //
1928 // nTransactionFee is the part of the fee that can be known before 2007 // nTransactionFee is the part of the fee that can be known before
1929 // the transaction exists. The rest is GetMinFee(), a function of 2008 // the transaction exists, and in production it is 0 -- it is only
1930 // the serialised size and therefore of how many inputs SelectCoins 2009 // ever assigned from the GUI preferences dialog, which a pool node
1931 // ends up picking, which cannot be predicted from here -- so this 2010 // does not have -- so including it here changes nothing on this
1932 // gate deliberately does NOT try to reserve it. Refusing to attempt 2011 // pool and is kept only because a GUI operator can set it. The
1933 // a payment the wallet could actually have made would be its own 2012 // rest is GetMinFee(), a function of the serialised size and
1934 // way of not paying a miner. That residual is handled after the 2013 // therefore of how many inputs SelectCoins ends up picking, which
1935 // fact, by classifying the failure below. 2014 // cannot be predicted from here -- so this gate deliberately does
2015 // NOT try to reserve it. Refusing to attempt a payment the wallet
2016 // could actually have made would be its own way of not paying a
2017 // miner. That residual is handled after the fact, by asking the
2018 // wallet why it refused -- see ClassifyPayoutSendFailure.
1936 int64 nSpendable = GetBalance(); 2019 int64 nSpendable = GetBalance();
1937 if (nSpendable < r.amount + nTransactionFee) { 2020 if (nSpendable < r.amount + nTransactionFee) {
1938 r.deferrals++; 2021 r.deferrals++;
@@ -1977,7 +2060,8 @@ static void PayoutThreadFn(void*)
1977 wtx.mapValue["pool_payout_address"] = r.address; 2060 wtx.mapValue["pool_payout_address"] = r.address;
1978 wtx.mapValue["pool_payout_amount"] = strprintf("%lld", r.amount); 2061 wtx.mapValue["pool_payout_amount"] = strprintf("%lld", r.amount);
1979 2062
1980 if (SendMoney(sc, r.amount, wtx)) { 2063 SendMoneyOutcome outcome;
2064 if (SendMoney(sc, r.amount, wtx, outcome)) {
1981 // The wallet holds the transaction before this returns, so a 2065 // The wallet holds the transaction before this returns, so a
1982 // crash between here and the ledger write is recoverable: the 2066 // crash between here and the ledger write is recoverable: the
1983 // probe above finds it by id+address+amount and does not 2067 // probe above finds it by id+address+amount and does not
@@ -1989,74 +2073,67 @@ static void PayoutThreadFn(void*)
1989 FormatMoney(r.amount).c_str(), r.address.c_str(), 2073 FormatMoney(r.amount).c_str(), r.address.c_str(),
1990 wtx.GetHash().ToString().substr(0, 12).c_str()); 2074 wtx.GetHash().ToString().substr(0, 12).c_str());
1991 } else { 2075 } else {
1992 // Why did it fail? The answer decides whether this costs a 2076 // Why did it fail? The answer used to decide whether the
1993 // retry, and the retry budget is what eventually erases a 2077 // payment eventually got erased, and it was decided by
1994 // miner's money -- so guessing here is how a pool keeps coin 2078 // guessing from a balance snapshot -- see
1995 // it owes. 2079 // ClassifyPayoutSendFailure for the arithmetic and what it
2080 // cost. The wallet now says what it did, and nothing here
2081 // erases anything.
1996 // 2082 //
1997 // Re-read the conditions rather than trusting the ones checked 2083 // The lock state is re-read rather than trusted from before
1998 // before the attempt: SendMoney takes cs_main and can block for 2084 // the attempt: SendMoney takes cs_main and can block for a
1999 // a long time, so the balance and the lock state may both have 2085 // long time, so it may have moved underneath us. The funding
2000 // moved underneath it. 2086 // answer does not need re-reading -- it is a statement about
2001 // 2087 // the attempt that was actually made.
2002 // Short of coin covers the size-dependent part of the fee that 2088 bool fLocked = IsWalletLocked();
2003 // the gate above deliberately does not reserve: if the balance 2089 int64 nAfter = GetBalance();
2004 // no longer covers amount + configured fee + one fee tier, the 2090
2005 // failure is a funding shortfall, not a fault. 2091 if (ClassifyPayoutSendFailure(outcome.result, fLocked)
2006 int64 nAfter = GetBalance(); 2092 == PAYOUT_FAILURE_DEFER) {
2007 bool fLocked = IsWalletLocked(); 2093 // Conditions are temporarily wrong. Wait.
2008 bool fUnfunded = nAfter < r.amount + nTransactionFee + CENT;
2009
2010 if (fLocked || fUnfunded) {
2011 // Conditions are temporarily wrong. Wait; do not spend the
2012 // budget that leads to a permanent write-off.
2013 r.deferrals++; 2094 r.deferrals++;
2014 r.retryAfter = GetTime() + 60; 2095 r.retryAfter = GetTime() + 60;
2015 if (r.deferrals == 1 || r.deferrals % 60 == 0) 2096 if (r.deferrals == 1 || r.deferrals % 60 == 0)
2016 LogPrint("payout", "[payout] deferring %s to %s -- send" 2097 LogPrint("payout", "[payout] deferring %s to %s -- send"
2017 " failed with %s (%s spendable, %s needed with" 2098 " failed with %s (%s spendable; the wallet"
2018 " fee headroom); waiting %d min so far\n", 2099 " needed a fee of %s for a transaction this"
2100 " size); waiting %d min so far\n",
2019 FormatMoney(r.amount).c_str(), r.address.c_str(), 2101 FormatMoney(r.amount).c_str(), r.address.c_str(),
2020 fLocked ? "the wallet locked" : "too little coin", 2102 fLocked ? "the wallet locked" : "too little coin",
2021 FormatMoney(nAfter).c_str(), 2103 FormatMoney(nAfter).c_str(),
2022 FormatMoney(r.amount + nTransactionFee + CENT).c_str(), 2104 FormatMoney(outcome.nFeeRequired).c_str(),
2023 r.deferrals); 2105 r.deferrals);
2024 ReschedulePayment(r); 2106 ReschedulePayment(r);
2025 } else if (r.retries < 1440) { 2107 } else {
2026 // A genuine fault: funded, unlocked, block on the main 2108 // Funded, unlocked, block on the main chain, and the
2027 // chain, and the wallet still would not build or accept 2109 // wallet still would not build, sign or accept the
2028 // the transaction. Retry with backoff. 2110 // transaction. That is worth shouting about; it is not
2111 // grounds to keep the money.
2112 //
2113 // There is deliberately no give-up branch. It used to
2114 // forfeit the debt after 1440 of these, which is not a
2115 // decidable state -- it is a count of how long we have
2116 // been asking, and it was reached by misclassifying a
2117 // funding shortfall as a fault. A debt that is never
2118 // written off cannot be written off wrongly. The payment
2119 // stays in flight, keeps its ledger entry, keeps being
2120 // reported in pool_status.json as owed, and keeps
2121 // retrying once a minute until the operator or the wallet
2122 // makes it possible.
2029 r.retries++; 2123 r.retries++;
2030 r.retryAfter = GetTime() + 60; 2124 r.retryAfter = GetTime() + 60;
2031 ReschedulePayment(r); 2125 ReschedulePayment(r);
2032 LogPrint("payout", "[payout] FAILED to pay %s to %s" 2126 // Every minute at first, then hourly: a fault that is not
2033 " (%s spendable, wallet unlocked) -- retry %d/1440" 2127 // going away must not turn the log into one line a minute
2034 " in 60s\n", 2128 // forever, and must not go quiet either.
2035 FormatMoney(r.amount).c_str(), r.address.c_str(), 2129 if (r.retries <= 5 || r.retries % 60 == 0)
2036 FormatMoney(nAfter).c_str(), r.retries); 2130 LogPrint("payout", "[payout] FAILED to pay %s to %s"
2037 } else { 2131 " (%s spendable, wallet unlocked, block %d on"
2038 // 1440 failures that were each individually impossible to 2132 " the main chain) -- attempt %d, retrying in"
2039 // explain by maturity, funding, the wallet being locked, or 2133 " 60s; this debt stands until it is paid\n",
2040 // a reorg. That is the only state in which this payment can 2134 FormatMoney(r.amount).c_str(), r.address.c_str(),
2041 // be called impossible rather than merely blocked. 2135 FormatMoney(nAfter).c_str(), r.blockHeight,
2042 const std::string reason = strprintf( 2136 r.retries);
2043 "wallet refused this payment %d times while funded"
2044 " (%s spendable), unlocked, and block %d on the main"
2045 " chain", r.retries, FormatMoney(nAfter).c_str(),
2046 r.blockHeight);
2047 LogPrint("payout", "[payout] GIVING UP on %s to %s: %s"
2048 " -- payment forfeited\n",
2049 FormatMoney(r.amount).c_str(), r.address.c_str(),
2050 reason.c_str());
2051 // Write the debt off in the ledger as well as dropping the
2052 // in-flight record. Under the survives-until-fully-paid
2053 // model the entry would otherwise never complete, and every
2054 // later flush would explode it again -- a forfeit that
2055 // silently becomes an infinite retry. The round proof is
2056 // told too, so the public record does not keep claiming the
2057 // address is owed.
2058 ForfeitPayoutRecipient(r, reason);
2059 ForgetPayment(r);
2060 } 2137 }
2061 } 2138 }
2062 } 2139 }
@@ -2850,13 +2927,19 @@ static void PayoutTestRemoveDir(const std::string& dir)
2850 } 2927 }
2851 RemoveDirectoryA(dir.c_str()); 2928 RemoveDirectoryA(dir.c_str());
2852#else 2929#else
2930 // One level of recursion, because CreateTransaction() opens a Berkeley DB
2931 // environment and BDB puts its logs in a "database" subdirectory. Without
2932 // this the scratch directory cannot be removed and the test leaves one
2933 // behind on every run, which is what d5b3503 was for.
2853 DIR* d = opendir(dir.c_str()); 2934 DIR* d = opendir(dir.c_str());
2854 if (d) { 2935 if (d) {
2855 struct dirent* ent; 2936 struct dirent* ent;
2856 while ((ent = readdir(d)) != NULL) { 2937 while ((ent = readdir(d)) != NULL) {
2857 std::string name = ent->d_name; 2938 std::string name = ent->d_name;
2858 if (name == "." || name == "..") continue; 2939 if (name == "." || name == "..") continue;
2859 unlink((dir + "/" + name).c_str()); 2940 const std::string path = dir + "/" + name;
2941 if (unlink(path.c_str()) != 0)
2942 PayoutTestRemoveDir(path);
2860 } 2943 }
2861 closedir(d); 2944 closedir(d);
2862 } 2945 }
@@ -2942,6 +3025,48 @@ static std::string PayoutTestAddWalletTx(const std::string& comment,
2942 return hash.GetHex(); 3025 return hash.GetHex();
2943} 3026}
2944 3027
3028// A real key, in the keystore, so a test wallet's outputs are IsMine() and can
3029// actually be signed -- both are needed for CreateTransaction to build the
3030// large transaction the fee schedule is being tested against. Inserted
3031// straight into the key maps rather than through AddKey(), which would also
3032// write it to a wallet.dat.
3033static std::string PayoutTestAddSpendableKey()
3034{
3035 CKey key;
3036 key.MakeNewKey();
3037 std::vector<unsigned char> vchPubKey = key.GetPubKey();
3038 CRITICAL_BLOCK(cs_mapKeys)
3039 {
3040 mapKeys[vchPubKey] = key.GetPrivKey();
3041 mapPubKeys[Hash160(vchPubKey)] = vchPubKey;
3042 }
3043 return Hash160ToAddress(Hash160(vchPubKey));
3044}
3045
3046// Give the wallet `n` spendable outputs of `each`, one transaction apiece --
3047// which is the granularity SelectCoins works at, and therefore the number of
3048// inputs the transaction spending them will carry.
3049//
3050// Deliberately not coinbases: a null prevout would make CWalletTx::GetCredit
3051// return 0 until COINBASE_SPENDABLE_DEPTH, and there is no chain here.
3052static void PayoutTestFundWallet(int n, int64 each, const std::string& address)
3053{
3054 const CScript sc = PayoutTestScriptFor(address);
3055 CRITICAL_BLOCK(cs_mapWallet)
3056 {
3057 for (int i = 0; i < n; i++) {
3058 CWalletTx wtx;
3059 wtx.vin.resize(1);
3060 wtx.vin[0].prevout.hash = (uint64)(i + 1);
3061 wtx.vin[0].prevout.n = 0;
3062 wtx.vout.resize(1);
3063 wtx.vout[0].nValue = each;
3064 wtx.vout[0].scriptPubKey = sc;
3065 mapWallet[wtx.GetHash()] = wtx;
3066 }
3067 }
3068}
3069
2945// Defined below with the event loop; the status-file publication test drives 3070// Defined below with the event loop; the status-file publication test drives
2946// it directly. 3071// it directly.
2947static void RefreshStats(int blocksFoundThisSession, uint64 roundShareTotal); 3072static void RefreshStats(int blocksFoundThisSession, uint64 roundShareTotal);
@@ -2967,11 +3092,32 @@ int RunPayoutLedgerSelfTest()
2967#else 3092#else
2968 unsigned long pid = (unsigned long)getpid(); 3093 unsigned long pid = (unsigned long)getpid();
2969#endif 3094#endif
2970 std::string dir = strprintf("payout_selftest_%d_%lu", (int)GetTime(), pid); 3095 // Absolute, and the process moves into it.
3096 //
3097 // Both are needed by the CreateTransaction section: Berkeley DB resolves
3098 // its log directory relative to the environment home, so a relative
3099 // datadir makes dbenv.open() fail with DB_RUNRECOVERY; and BDB opens
3100 // db.log relative to the working directory, which is src/ during `make
3101 // tests`. Moving in puts it inside the scratch directory, where it dies
3102 // with everything else.
3103 std::string cwd = ".";
3104 {
3105#ifdef _WIN32
3106 char buf[MAX_PATH];
3107 if (GetCurrentDirectoryA(MAX_PATH, buf) > 0) cwd = buf;
3108#else
3109 char buf[4096];
3110 if (getcwd(buf, sizeof(buf)) != NULL) cwd = buf;
3111#endif
3112 }
3113 std::string dir = cwd + "/" +
3114 strprintf("payout_selftest_%d_%lu", (int)GetTime(), pid);
2971#ifdef _WIN32 3115#ifdef _WIN32
2972 CreateDirectoryA(dir.c_str(), NULL); 3116 CreateDirectoryA(dir.c_str(), NULL);
3117 SetCurrentDirectoryA(dir.c_str());
2973#else 3118#else
2974 mkdir(dir.c_str(), 0700); 3119 mkdir(dir.c_str(), 0700);
3120 if (chdir(dir.c_str()) != 0) { /* stay put; the paths are absolute anyway */ }
2975#endif 3121#endif
2976 strSetDataDir = dir; 3122 strSetDataDir = dir;
2977 fprintf(stdout, " scratch datadir: %s\n", dir.c_str()); 3123 fprintf(stdout, " scratch datadir: %s\n", dir.c_str());
@@ -3494,7 +3640,141 @@ int RunPayoutLedgerSelfTest()
3494 strPoolRoundsFile = savedRoundsFile; 3640 strPoolRoundsFile = savedRoundsFile;
3495 } 3641 }
3496 3642
3497 // -- 11. No payout mutex is held across the status-file write ------------ 3643 // -- 11. A send that failed for want of coin is not a fault --------------
3644 //
3645 // The defect this replaces: the classifier decided "was this a funding
3646 // problem?" by re-reading GetBalance() and allowing amount +
3647 // nTransactionFee + CENT. nTransactionFee is 0 on a headless node, and
3648 // GetMinFee() is a step function -- 0 below 10,000 bytes, 11 * CENT at it
3649 // -- so the allowance was either unnecessary or eleven times too small,
3650 // and the ledger's own retry budget then wrote the debt off after 1440
3651 // repeats of the same stable condition.
3652 //
3653 // This is tested against a real wallet and the real CreateTransaction, not
3654 // against injected values: the honest question is not "does my enum
3655 // switch work" but "does a wallet holding many small coins actually report
3656 // the state I think it does". 60 outputs of 1 BTF give ~180 signed P2PKH
3657 // bytes each, which is where the fee schedule steps. Nothing is committed
3658 // or broadcast -- CreateTransaction only builds.
3659 {
3660 PayoutTestResetState();
3661 CRITICAL_BLOCK(cs_mapWallet)
3662 mapWallet.clear();
3663
3664 // CreateTransaction opens CTxDB("r"), which throws if blkindex.dat is
3665 // not there. Create it in the scratch datadir first.
3666 bool dbOk = true;
3667 try {
3668 CTxDB txdb("cr");
3669 } catch (const std::exception&) {
3670 dbOk = false;
3671 }
3672 check(dbOk, "a scratch block index exists for CreateTransaction to open");
3673
3674 const std::string walletAddr = PayoutTestAddSpendableKey();
3675 const std::string payee = PayoutTestAddress(0x77);
3676 const CScript payeeScript = PayoutTestScriptFor(payee);
3677
3678 // -- the >= 10 KB case: 60 small coins, balance = amount + 0.05 ------
3679 PayoutTestFundWallet(60, 1 * COIN, walletAddr);
3680 const int64 balance = GetBalance();
3681 check(balance == 60 * COIN,
3682 "the test wallet holds 60 separately spendable coins");
3683
3684 const int64 amount = balance - 5 * CENT;
3685 // The pre-send gate in PayoutThreadFn passes: the balance covers the
3686 // amount and the only fee that can be known in advance.
3687 check(balance >= amount + nTransactionFee,
3688 "the pre-send gate would let this payment through");
3689
3690 CWalletTx wtx;
3691 SendMoneyOutcome outcome;
3692 int64 feeRequired = 0;
3693 WalletSendResult result = WALLET_SEND_OK;
3694 bool built = true;
3695 if (dbOk) {
3696 try {
3697 built = CreateTransaction(payeeScript, amount, wtx, feeRequired,
3698 &result);
3699 } catch (const std::exception&) {
3700 built = true; // report as a failure below
3701 }
3702 }
3703 check(dbOk && !built,
3704 "a wallet of many small coins cannot fund amount + the fee its"
3705 " own size demands");
3706 check(dbOk && result == WALLET_SEND_INSUFFICIENT_FUNDS,
3707 "the wallet reports that as a funding shortfall, not as a"
3708 " failure to build");
3709 // GetMinFee(fDiscount) returns 0 below 10,000 bytes and
3710 // (1 + bytes/1000) * CENT at or above, so a required fee of 11 CENT or
3711 // more IS the statement that the transaction crossed 10 KB. Measured
3712 // through the real serialiser rather than asserted.
3713 check(dbOk && feeRequired >= 11 * CENT,
3714 "the transaction it built crossed 10,000 bytes, so the fee"
3715 " stepped from 0 to at least 11 CENT");
3716
3717 // The defect, stated as arithmetic. The old classifier asked whether
3718 // the balance covered amount + nTransactionFee + CENT; it did, so it
3719 // called a permanent funding shortfall a fault and started counting
3720 // towards a write-off.
3721 check(!(balance < amount + nTransactionFee + CENT),
3722 "the reserve this replaces would have judged this send a fault");
3723 check(balance < amount + feeRequired,
3724 "while the fee actually required was more than the balance had");
3725
3726 outcome.result = result;
3727 outcome.nFeeRequired = feeRequired;
3728 check(dbOk && ClassifyPayoutSendFailure(outcome.result, false)
3729 == PAYOUT_FAILURE_DEFER,
3730 "a >= 10 KB send that ran out of coin is deferred, not counted"
3731 " against the payment");
3732
3733 // -- the < 10 KB case: no reserve is needed at all -------------------
3734 //
3735 // The other half of the arithmetic. Below the step the required fee is
3736 // 0, so a reserve of any size is a reason to refuse a payment the
3737 // wallet could have made -- which is its own way of not paying a
3738 // miner.
3739 CRITICAL_BLOCK(cs_mapWallet)
3740 mapWallet.clear();
3741 PayoutTestFundWallet(3, 1 * COIN, walletAddr);
3742 const int64 smallAmount = 3 * COIN - 5 * CENT;
3743 CWalletTx smallTx;
3744 int64 smallFee = -1;
3745 WalletSendResult smallResult = WALLET_SEND_FAILED;
3746 bool smallBuilt = false;
3747 if (dbOk) {
3748 try {
3749 smallBuilt = CreateTransaction(payeeScript, smallAmount, smallTx,
3750 smallFee, &smallResult);
3751 } catch (const std::exception&) {
3752 smallBuilt = false;
3753 }
3754 }
3755 check(dbOk && smallBuilt && smallResult == WALLET_SEND_OK,
3756 "the same balance pays a small transaction with no headroom at"
3757 " all");
3758 check(dbOk && smallFee == 0,
3759 "because below 10,000 bytes the required fee is zero");
3760
3761 // -- and the classification of every other answer --------------------
3762 check(ClassifyPayoutSendFailure(WALLET_SEND_INSUFFICIENT_FUNDS, false)
3763 == PAYOUT_FAILURE_DEFER &&
3764 ClassifyPayoutSendFailure(WALLET_SEND_INSUFFICIENT_FUNDS, true)
3765 == PAYOUT_FAILURE_DEFER &&
3766 ClassifyPayoutSendFailure(WALLET_SEND_FAILED, true)
3767 == PAYOUT_FAILURE_DEFER,
3768 "short of coin or unable to sign is always a deferral");
3769 check(ClassifyPayoutSendFailure(WALLET_SEND_FAILED, false)
3770 == PAYOUT_FAILURE_FAULT,
3771 "funded and unlocked and still refused is a fault");
3772
3773 CRITICAL_BLOCK(cs_mapWallet)
3774 mapWallet.clear();
3775 }
3776
3777 // -- 12. No payout mutex is held across the status-file write ------------
3498 // 3778 //
3499 // RefreshStats runs on the event loop -- the thread that owns every 3779 // RefreshStats runs on the event loop -- the thread that owns every
3500 // miner's socket -- and used to hold gStatsMutex and gPayoutLedgerMutex at 3780 // miner's socket -- and used to hold gStatsMutex and gPayoutLedgerMutex at
@@ -3628,6 +3908,19 @@ int RunPayoutLedgerSelfTest()
3628 PayoutTestResetState(); 3908 PayoutTestResetState();
3629 CRITICAL_BLOCK(cs_mapWallet) 3909 CRITICAL_BLOCK(cs_mapWallet)
3630 mapWallet.clear(); 3910 mapWallet.clear();
3911 // Out of the scratch directory before removing it, and out of the key maps
3912 // too: the keys this test generated are process-local, but leaving them in
3913 // the keystore would let a later test think a script was its own.
3914 CRITICAL_BLOCK(cs_mapKeys)
3915 {
3916 mapKeys.clear();
3917 mapPubKeys.clear();
3918 }
3919#ifdef _WIN32
3920 SetCurrentDirectoryA(cwd.c_str());
3921#else
3922 if (chdir(cwd.c_str()) != 0) { /* nothing useful to do about it */ }
3923#endif
3631 PayoutTestRemoveDir(dir); 3924 PayoutTestRemoveDir(dir);
3632 strSetDataDir = savedDataDir; 3925 strSetDataDir = savedDataDir;
3633 nBestHeight = savedBestHeight; 3926 nBestHeight = savedBestHeight;