From a5e6d72339f28699bc356603f695bd620be37e83 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sat, 16 Jul 2011 19:01:05 +0200 Subject: add sendmany support --- src/qt/walletmodel.cpp | 91 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 67 insertions(+), 24 deletions(-) (limited to 'src/qt/walletmodel.cpp') diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index afe095c977..6e4b814d12 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -7,6 +7,7 @@ #include "headers.h" #include +#include WalletModel::WalletModel(CWallet *wallet, QObject *parent) : QObject(parent), wallet(wallet), optionsModel(0), addressTableModel(0), @@ -54,63 +55,105 @@ void WalletModel::update() addressTableModel->update(); } -WalletModel::StatusCode WalletModel::sendCoins(const QString &payTo, qint64 payAmount, const QString &addToAddressBookAs) +bool WalletModel::validateAddress(const QString &address) { uint160 hash160 = 0; - bool valid = false; - if(!AddressToHash160(payTo.toUtf8().constData(), hash160)) + return AddressToHash160(address.toStdString(), hash160); +} + +WalletModel::SendCoinsReturn WalletModel::sendCoins(const QList &recipients) +{ + qint64 total = 0; + QSet setAddress; + QString hex; + + if(recipients.empty()) { - return InvalidAddress; + return OK; } - if(payAmount <= 0) + // Pre-check input data for validity + foreach(const SendCoinsRecipient &rcp, recipients) { - return InvalidAmount; + uint160 hash160 = 0; + + if(!AddressToHash160(rcp.address.toUtf8().constData(), hash160)) + { + return InvalidAddress; + } + setAddress.insert(rcp.address); + + if(rcp.amount <= 0) + { + return InvalidAmount; + } + total += rcp.amount; } - if(payAmount > getBalance()) + if(recipients.size() > setAddress.size()) + { + return DuplicateAddress; + } + + if(total > getBalance()) { return AmountExceedsBalance; } - if((payAmount + nTransactionFee) > getBalance()) + if((total + nTransactionFee) > getBalance()) { - return AmountWithFeeExceedsBalance; + return SendCoinsReturn(AmountWithFeeExceedsBalance, nTransactionFee); } CRITICAL_BLOCK(cs_main) + CRITICAL_BLOCK(wallet->cs_mapWallet) { - // Send to bitcoin address + // Sendmany + std::vector > vecSend; + foreach(const SendCoinsRecipient &rcp, recipients) + { + CScript scriptPubKey; + scriptPubKey.SetBitcoinAddress(rcp.address.toStdString()); + vecSend.push_back(make_pair(scriptPubKey, rcp.amount)); + } + CWalletTx wtx; - CScript scriptPubKey; - scriptPubKey << OP_DUP << OP_HASH160 << hash160 << OP_EQUALVERIFY << OP_CHECKSIG; + CReserveKey keyChange(wallet); + int64 nFeeRequired = 0; + bool fCreated = wallet->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired); - std::string strError = wallet->SendMoney(scriptPubKey, payAmount, wtx, true); - if (strError == "") + if(!fCreated) { - // OK + if((total + nFeeRequired) > wallet->GetBalance()) + { + return SendCoinsReturn(AmountWithFeeExceedsBalance, nFeeRequired); + } + return TransactionCreationFailed; } - else if (strError == "ABORTED") + if(!ThreadSafeAskFee(nFeeRequired, tr("Sending...").toStdString(), NULL)) { return Aborted; } - else + if(!wallet->CommitTransaction(wtx, keyChange)) { - emit error(tr("Sending..."), QString::fromStdString(strError)); - return MiscError; + return TransactionCommitFailed; } + hex = QString::fromStdString(wtx.GetHash().GetHex()); } // Add addresses that we've sent to to the address book - std::string strAddress = payTo.toStdString(); - CRITICAL_BLOCK(wallet->cs_mapAddressBook) + foreach(const SendCoinsRecipient &rcp, recipients) { - if (!wallet->mapAddressBook.count(strAddress)) - wallet->SetAddressBookName(strAddress, addToAddressBookAs.toStdString()); + std::string strAddress = rcp.address.toStdString(); + CRITICAL_BLOCK(wallet->cs_mapAddressBook) + { + if (!wallet->mapAddressBook.count(strAddress)) + wallet->SetAddressBookName(strAddress, rcp.label.toStdString()); + } } - return OK; + return SendCoinsReturn(OK, 0, hex); } OptionsModel *WalletModel::getOptionsModel() -- cgit v1.2.3