Skip to content

Commit

Permalink
Fixed fee calculation
Browse files Browse the repository at this point in the history
  • Loading branch information
psolstice committed Jun 7, 2024
1 parent 8cc6cc4 commit c5a5c82
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 11 deletions.
27 changes: 17 additions & 10 deletions src/qt/sendcoinsdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -320,24 +320,25 @@ void SendCoinsDialog::on_sendButton_clicked()
bool fGoThroughTransparentAddress = false;
__decltype(recipients) exchangeRecipients;
CScript intermediateAddressScript;
CAmount extraFee = 0;

if (fAnonymousMode && exchangeAddressCount > 0) {
CAmount exchangeAddressAmount = 0;
bool fSubtractFeeFromIntermediateAddressAmount = false;
// if the transaction is performed in two stages through the intermediate address we need to calculate the size of the second transaction
uint32_t secondTxSize = 8 /*CTransaction: nVersion, nLockTime*/ + 1 /*vinSize*/ + 148 /*vin[0]*/ + 20 /*safety*/ + 1 /*voutSize*/;

fGoThroughTransparentAddress = true;

// remove exchange addresses from recipients array and add them to exchangeRecipients array
for(int i = 0; i < recipients.size(); ){
if (model->validateExchangeAddress(recipients[i].address)) {
exchangeAddressAmount += recipients[i].amount;
recipients[i].fSubtractFeeFromAmount = true;
// we use different fee calculation system and therefore can't reliably do the calculation
// of fee for the second transaction if some of recipients have this flag set
recipients[i].fSubtractFeeFromAmount = false;
exchangeRecipients.push_back(recipients[i]);

// It's not clear if we should subtract fee from the intermediate address amount if
// there are conflicting "fSubractFeeFromAmount" flags in the exchangeRecipients array.
// For now, we use the flag from the last exchange recipient.
fSubtractFeeFromIntermediateAddressAmount = recipients[i].fSubtractFeeFromAmount;
secondTxSize += 8 /*amount*/ + 1 /*scriptSize*/ + 26 /*scriptPubKey*/;

recipients.erase(recipients.begin() + i);
}
Expand All @@ -359,10 +360,12 @@ void SendCoinsDialog::on_sendButton_clicked()
pwalletMain->SetAddressBook(newKey.GetID(), "", "receive");
intermediateAddressScript = GetScriptForDestination(newKey.GetID());

extraFee = CWallet::GetMinimumFee(secondTxSize, 0, mempool);

SendCoinsRecipient newRecipient;
newRecipient.address = CBitcoinAddress(newKey.GetID()).ToString().c_str();
newRecipient.amount = exchangeAddressAmount;
newRecipient.fSubtractFeeFromAmount = fSubtractFeeFromIntermediateAddressAmount;
newRecipient.amount = exchangeAddressAmount + extraFee;
newRecipient.fSubtractFeeFromAmount = false;
recipients.push_back(newRecipient);
}

Expand Down Expand Up @@ -553,7 +556,10 @@ void SendCoinsDialog::on_sendButton_clicked()
questionString.append(" (" + QString::number(txSize / 1000) + " kB)");

if (fGoThroughTransparentAddress) {
questionString.append(tr(". Note: the transaction will go through a transparent address, additional fees may apply."));
questionString.append(tr(". Note: the transaction will go through a transparent address, fee for the second transaction is "));
questionString.append("<span style='color:#aa0000;'>");
questionString.append(BitcoinUnits::formatHtmlWithUnit(model->getOptionsModel()->getDisplayUnit(), extraFee));
questionString.append("</span>.");
}
}

Expand Down Expand Up @@ -653,6 +659,7 @@ void SendCoinsDialog::on_sendButton_clicked()

CCoinControl ctrl;
ctrl.fAllowOtherInputs = false;
ctrl.fNoChange = true;
ctrl.Select(outpoint);

WalletModelTransaction secondTransaction(exchangeRecipients);
Expand All @@ -668,7 +675,7 @@ void SendCoinsDialog::on_sendButton_clicked()
return;
}

sendStatus = model->sendCoins(currentTransaction);
sendStatus = model->sendCoins(secondTransaction);
// process sendStatus and on error generate message shown to user
processSendCoinsReturn(sendStatus);
}
Expand Down
3 changes: 3 additions & 0 deletions src/wallet/coincontrol.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ class CCoinControl
{
public:
CTxDestination destChange;
//! If true, don't use any change
bool fNoChange;
//! If false, allows unselected inputs, but requires all selected inputs be used
bool fAllowOtherInputs;
//! Includes watch only addresses which match the ISMINE_WATCH_SOLVABLE criteria
Expand All @@ -49,6 +51,7 @@ class CCoinControl
void SetNull()
{
destChange = CNoDestination();
fNoChange = false;
fAllowOtherInputs = false;
fRequireAllInputs = true;
fAllowWatchOnly = false;
Expand Down
2 changes: 1 addition & 1 deletion src/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4450,7 +4450,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletT
const CAmount nChange = nValueIn - nValueToSelect;
CTxOut newTxOut;

if (nChange > 0)
if (nChange > 0 && !(coinControl && coinControl->fNoChange))
{
// Fill a vout to ourself
// TODO: pass in scriptChange instead of reservekey so
Expand Down

0 comments on commit c5a5c82

Please sign in to comment.