Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/coincontrol.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ class CCoinControl
CTxDestination destChange;
bool useObfuScation;
bool useSwiftTX;
bool fSplitBlock;
int nSplitBlock;
//! 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 @@ -36,6 +38,8 @@ class CCoinControl
fAllowOtherInputs = false;
fAllowWatchOnly = false;
nMinimumTotalFee = 0;
fSplitBlock = false;
nSplitBlock = 1;
}

bool HasSelected() const
Expand Down
3 changes: 2 additions & 1 deletion src/qt/coincontroldialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@

using namespace std;
QList<CAmount> CoinControlDialog::payAmounts;
int CoinControlDialog::nSplitBlockDummy;
CCoinControl* CoinControlDialog::coinControl = new CCoinControl();

CoinControlDialog::CoinControlDialog(QWidget *parent) :
Expand Down Expand Up @@ -586,7 +587,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
if (nQuantity > 0)
{
// Bytes
nBytes = nBytesInputs + ((CoinControlDialog::payAmounts.size() > 0 ? CoinControlDialog::payAmounts.size() + 1 : 2) * 34) + 10; // always assume +1 output for change here
nBytes = nBytesInputs + ((CoinControlDialog::payAmounts.size() > 0 ? CoinControlDialog::payAmounts.size() + max(1, CoinControlDialog::nSplitBlockDummy) : 2) * 34) + 10; // always assume +1 output for change here

// Priority
double mempoolEstimatePriority = mempool.estimatePriority(nTxConfirmTarget);
Expand Down
1 change: 1 addition & 0 deletions src/qt/coincontroldialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class CoinControlDialog : public QDialog

static QList<CAmount> payAmounts;
static CCoinControl *coinControl;
static int nSplitBlockDummy;

private:
Ui::CoinControlDialog *ui;
Expand Down
43 changes: 39 additions & 4 deletions src/qt/forms/sendcoinsdialog.ui
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,7 @@
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayoutCoinControl4" stretch="0,0,0">
<layout class="QHBoxLayout" name="horizontalLayoutCoinControl4" stretch="0,0,0,0,0,0,0">
<property name="spacing">
<number>12</number>
</property>
Expand Down Expand Up @@ -564,6 +564,40 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="splitBlockCheckBox">
<property name="text">
<string>Split UTXO</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="splitBlockLineEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>50</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="placeholderText">
<string># of outputs</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="labelBlockSizeText">
<property name="text">
<string>UTXO Size:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="labelBlockSize">
<property name="text">
<string>0 DNET</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="labelCoinControlChangeLabel">
<property name="sizePolicy">
Expand Down Expand Up @@ -617,7 +651,7 @@
<x>0</x>
<y>0</y>
<width>830</width>
<height>91</height>
<height>95</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,1">
Expand Down Expand Up @@ -1151,7 +1185,7 @@
<string>Custom:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTop</set>
<set>Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing</set>
</property>
</widget>
</item>
Expand All @@ -1165,7 +1199,8 @@
</property>
</widget>
</item>
<item><widget class="QLabel" name="labelSmartFee2">
<item row="0" column="0">
<widget class="QLabel" name="labelSmartFee2">
<property name="text">
<string>(Smart fee not initialized yet. This usually takes a few blocks...)</string>
</property>
Expand Down
8 changes: 8 additions & 0 deletions src/qt/res/css/drk-1.css
Original file line number Diff line number Diff line change
Expand Up @@ -1837,6 +1837,14 @@ QDialog#SendCoinsDialog .QFrame#frameCoinControl .QCheckBox#checkBoxCoinControlC
color:#ffffff;
}

/*******************************/
/* SPLIT BLOCK CHECK BOX */
/*******************************/

QDialog#SendCoinsDialog .QFrame#frameCoinControl .QCheckBox#splitBlockCheckBox {
color:#ffffff;
}

/*******************************/
/* CUSTOM CHANGE ADDRESS */
/*******************************/
Expand Down
64 changes: 64 additions & 0 deletions src/qt/sendcoinsdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ SendCoinsDialog::SendCoinsDialog(QWidget *parent) :
connect(ui->checkBoxCoinControlChange, SIGNAL(stateChanged(int)), this, SLOT(coinControlChangeChecked(int)));
connect(ui->lineEditCoinControlChange, SIGNAL(textEdited(const QString &)), this, SLOT(coinControlChangeEdited(const QString &)));

// UTXO Splitter
connect(ui->splitBlockCheckBox, SIGNAL(stateChanged(int)), this, SLOT(splitBlockChecked(int)));
connect(ui->splitBlockLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(splitBlockLineEditChanged(const QString &)));

// DarkNet specific
QSettings settings;
if (!settings.contains("bUseObfuScation"))
Expand Down Expand Up @@ -225,6 +229,19 @@ void SendCoinsDialog::on_sendButton_clicked()
for(int i = 0; i < ui->entries->count(); ++i)
{
SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());

//UTXO splitter - address should be our own
CBitcoinAddress address = entry->getValue().address.toStdString();
if(!model->isMine(address) && ui->splitBlockCheckBox->checkState() == Qt::Checked)
{
CoinControlDialog::coinControl->fSplitBlock = false;
ui->splitBlockCheckBox->setCheckState(Qt::Unchecked);
QMessageBox::warning(this, tr("Send Coins"),
tr("The split block tool does not work when sending to outside addresses. Try again."),
QMessageBox::Ok, QMessageBox::Ok);
return;
}

if(entry)
{
if(entry->validate())
Expand All @@ -243,6 +260,22 @@ void SendCoinsDialog::on_sendButton_clicked()
return;
}

//set split block in model
CoinControlDialog::coinControl->fSplitBlock = ui->splitBlockCheckBox->checkState() == Qt::Checked;

if (ui->entries->count() > 1 && ui->splitBlockCheckBox->checkState() == Qt::Checked)
{
CoinControlDialog::coinControl->fSplitBlock = false;
ui->splitBlockCheckBox->setCheckState(Qt::Unchecked);
QMessageBox::warning(this, tr("Send Coins"),
tr("The split block tool does not work with multiple addresses. Try again."),
QMessageBox::Ok, QMessageBox::Ok);
return;
}

if (CoinControlDialog::coinControl->fSplitBlock)
CoinControlDialog::coinControl->nSplitBlock = int(ui->splitBlockLineEdit->text().toInt());

QString strFunds = tr("using") + " <b>" + tr("anonymous funds") + "</b>";
QString strFee = "";
recipients[0].inputType = ONLY_DENOMINATED;
Expand Down Expand Up @@ -305,6 +338,11 @@ void SendCoinsDialog::on_sendButton_clicked()
recipientElement = tr("%1 to %2").arg(amount, address);
}

if(fSplitBlock)
{
recipientElement.append(tr(" split into %1 outputs using the UTXO splitter.").arg(CoinControlDialog::coinControl->nSplitBlock));
}

formatted.append(recipientElement);
}

Expand Down Expand Up @@ -755,6 +793,32 @@ void SendCoinsDialog::updateSmartFeeLabel()
updateFeeMinimizedLabel();
}

// UTXO splitter
void SendCoinsDialog::splitBlockChecked(int state)
{
if (model)
{
CoinControlDialog::coinControl->fSplitBlock = (state == Qt::Checked);
fSplitBlock = (state == Qt::Checked);
ui->splitBlockLineEdit->setEnabled((state == Qt::Checked));
ui->labelBlockSizeText->setEnabled((state == Qt::Checked));
ui->labelBlockSize->setEnabled((state == Qt::Checked));
coinControlUpdateLabels();
}
}

//UTXO splitter
void SendCoinsDialog::splitBlockLineEditChanged(const QString & text)
{
double nAfterFee = ui->labelCoinControlAfterFee->text().left(ui->labelCoinControlAfterFee->text().indexOf(" ")).replace("~", "").toDouble();
double nSize = nAfterFee;
if (nAfterFee > 0 && text.toDouble() > 0)
nSize = nAfterFee / text.toDouble();
ui->labelBlockSize->setText(QString::number(nSize));
CoinControlDialog::nSplitBlockDummy = text.toInt();
coinControlUpdateLabels();
}

// Coin Control: copy label "Quantity" to clipboard
void SendCoinsDialog::coinControlClipboardQuantity()
{
Expand Down
3 changes: 3 additions & 0 deletions src/qt/sendcoinsdialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class SendCoinsDialog : public QDialog
void setAddress(const QString &address);
void pasteEntry(const SendCoinsRecipient &rv);
bool handlePaymentRequest(const SendCoinsRecipient &recipient);
bool fSplitBlock;

public slots:
void clear();
Expand Down Expand Up @@ -89,6 +90,8 @@ private slots:
void coinControlClipboardPriority();
void coinControlClipboardLowOutput();
void coinControlClipboardChange();
void splitBlockChecked(int);
void splitBlockLineEditChanged(const QString & text);
void setMinimumFee();
void updateFeeSectionControls();
void updateMinFeeLabel();
Expand Down
5 changes: 5 additions & 0 deletions src/qt/walletmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -719,3 +719,8 @@ bool WalletModel::saveReceiveRequest(const std::string &sAddress, const int64_t
else
return wallet->AddDestData(dest, key, sRequest);
}

bool WalletModel::isMine(CBitcoinAddress address)
{
return IsMine(*wallet, address.Get());
}
1 change: 1 addition & 0 deletions src/qt/walletmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ class WalletModel : public QObject
UnlockContext requestUnlock(bool relock=false);

bool getPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const;
bool isMine(CBitcoinAddress address);
void getOutputs(const std::vector<COutPoint>& vOutpoints, std::vector<COutput>& vOutputs);
bool isSpent(const COutPoint& outpoint) const;
void listCoins(std::map<QString, std::vector<COutput> >& mapCoins) const;
Expand Down
36 changes: 30 additions & 6 deletions src/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2256,16 +2256,40 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, CAmount> >& vecSend,

CAmount nTotalValue = nValue + nFeeRet;
double dPriority = 0;

// vouts to the payees
BOOST_FOREACH (const PAIRTYPE(CScript, CAmount)& s, vecSend)
if(coinControl && !coinControl->fSplitBlock)
{
CTxOut txout(s.second, s.first);
if (txout.IsDust(::minRelayTxFee))
BOOST_FOREACH (const PAIRTYPE(CScript, CAmount)& s, vecSend)
{
strFailReason = _("Transaction amount too small");
return false;
CTxOut txout(s.second, s.first);
if (txout.IsDust(::minRelayTxFee))
{
strFailReason = _("Transaction amount too small");
return false;
}
txNew.vout.push_back(txout);
}
}
else //UTXO Splitter Transaction
{
int nSplitBlock = coinControl->nSplitBlock;
if(nSplitBlock < 1)
nSplitBlock = 1;

BOOST_FOREACH (const PAIRTYPE(CScript, CAmount)& s, vecSend)
{
for(int i = 0; i < nSplitBlock; i++)
{
if(i == nSplitBlock - 1)
{
uint64_t nRemainder = s.second % nSplitBlock;
txNew.vout.push_back(CTxOut((s.second / nSplitBlock) + nRemainder, s.first));
}
else
txNew.vout.push_back(CTxOut(s.second / nSplitBlock, s.first));
}
}
txNew.vout.push_back(txout);
}

// Choose coins to use
Expand Down