Skip to content

Commit 5c8ff0d

Browse files
committed
Introduce wrappers around CBitcoinAddress
This patch removes the need for the intermediary Base58 type CBitcoinAddress, by providing {Encode,Decode,IsValid}Destination function that directly operate on the conversion between strings and CTxDestination.
1 parent 6866b49 commit 5c8ff0d

26 files changed

+299
-277
lines changed

src/base58.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,3 +318,25 @@ bool CBitcoinSecret::SetString(const std::string& strSecret)
318318
{
319319
return SetString(strSecret.c_str());
320320
}
321+
322+
std::string EncodeDestination(const CTxDestination& dest)
323+
{
324+
CBitcoinAddress addr(dest);
325+
if (!addr.IsValid()) return "";
326+
return addr.ToString();
327+
}
328+
329+
CTxDestination DecodeDestination(const std::string& str)
330+
{
331+
return CBitcoinAddress(str).Get();
332+
}
333+
334+
bool IsValidDestinationString(const std::string& str, const CChainParams& params)
335+
{
336+
return CBitcoinAddress(str).IsValid(params);
337+
}
338+
339+
bool IsValidDestinationString(const std::string& str)
340+
{
341+
return CBitcoinAddress(str).IsValid();
342+
}

src/base58.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,4 +167,9 @@ template<typename K, int Size, CChainParams::Base58Type Type> class CBitcoinExtK
167167
typedef CBitcoinExtKeyBase<CExtKey, BIP32_EXTKEY_SIZE, CChainParams::EXT_SECRET_KEY> CBitcoinExtKey;
168168
typedef CBitcoinExtKeyBase<CExtPubKey, BIP32_EXTKEY_SIZE, CChainParams::EXT_PUBLIC_KEY> CBitcoinExtPubKey;
169169

170+
std::string EncodeDestination(const CTxDestination& dest);
171+
CTxDestination DecodeDestination(const std::string& str);
172+
bool IsValidDestinationString(const std::string& str);
173+
bool IsValidDestinationString(const std::string& str, const CChainParams& params);
174+
170175
#endif // BITCOIN_BASE58_H

src/bitcoin-tx.cpp

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -271,11 +271,11 @@ static void MutateTxAddOutAddr(CMutableTransaction& tx, const std::string& strIn
271271

272272
// extract and validate ADDRESS
273273
std::string strAddr = vStrInputParts[1];
274-
CBitcoinAddress addr(strAddr);
275-
if (!addr.IsValid())
274+
CTxDestination destination = DecodeDestination(strAddr);
275+
if (!IsValidDestination(destination)) {
276276
throw std::runtime_error("invalid TX output address");
277-
// build standard output script via GetScriptForDestination()
278-
CScript scriptPubKey = GetScriptForDestination(addr.Get());
277+
}
278+
CScript scriptPubKey = GetScriptForDestination(destination);
279279

280280
// construct TxOut, append to transaction output list
281281
CTxOut txout(value, scriptPubKey);
@@ -314,10 +314,8 @@ static void MutateTxAddOutPubKey(CMutableTransaction& tx, const std::string& str
314314
scriptPubKey = GetScriptForWitness(scriptPubKey);
315315
}
316316
if (bScriptHash) {
317-
// Get the address for the redeem script, then call
318-
// GetScriptForDestination() to construct a P2SH scriptPubKey.
319-
CBitcoinAddress redeemScriptAddr(scriptPubKey);
320-
scriptPubKey = GetScriptForDestination(redeemScriptAddr.Get());
317+
// Get the ID for the script, and then construct a P2SH destination for it.
318+
scriptPubKey = GetScriptForDestination(CScriptID(scriptPubKey));
321319
}
322320

323321
// construct TxOut, append to transaction output list
@@ -381,10 +379,8 @@ static void MutateTxAddOutMultiSig(CMutableTransaction& tx, const std::string& s
381379
scriptPubKey = GetScriptForWitness(scriptPubKey);
382380
}
383381
if (bScriptHash) {
384-
// Get the address for the redeem script, then call
385-
// GetScriptForDestination() to construct a P2SH scriptPubKey.
386-
CBitcoinAddress addr(scriptPubKey);
387-
scriptPubKey = GetScriptForDestination(addr.Get());
382+
// Get the ID for the script, and then construct a P2SH destination for it.
383+
scriptPubKey = GetScriptForDestination(CScriptID(scriptPubKey));
388384
}
389385

390386
// construct TxOut, append to transaction output list
@@ -444,11 +440,10 @@ static void MutateTxAddOutScript(CMutableTransaction& tx, const std::string& str
444440
}
445441

446442
if (bSegWit) {
447-
scriptPubKey = GetScriptForWitness(scriptPubKey);
443+
scriptPubKey = GetScriptForWitness(scriptPubKey);
448444
}
449445
if (bScriptHash) {
450-
CBitcoinAddress addr(scriptPubKey);
451-
scriptPubKey = GetScriptForDestination(addr.Get());
446+
scriptPubKey = GetScriptForDestination(CScriptID(scriptPubKey));
452447
}
453448

454449
// construct TxOut, append to transaction output list

src/core_write.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,9 @@ void ScriptPubKeyToUniv(const CScript& scriptPubKey,
148148
out.pushKV("type", GetTxnOutputType(type));
149149

150150
UniValue a(UniValue::VARR);
151-
for (const CTxDestination& addr : addresses)
152-
a.push_back(CBitcoinAddress(addr).ToString());
151+
for (const CTxDestination& addr : addresses) {
152+
a.push_back(EncodeDestination(addr));
153+
}
153154
out.pushKV("addresses", a);
154155
}
155156

src/qt/addresstablemodel.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,14 @@ class AddressTablePriv
8282
LOCK(wallet->cs_wallet);
8383
for (const std::pair<CTxDestination, CAddressBookData>& item : wallet->mapAddressBook)
8484
{
85-
const CBitcoinAddress& address = item.first;
86-
bool fMine = IsMine(*wallet, address.Get());
85+
const CTxDestination& address = item.first;
86+
bool fMine = IsMine(*wallet, address);
8787
AddressTableEntry::Type addressType = translateTransactionType(
8888
QString::fromStdString(item.second.purpose), fMine);
8989
const std::string& strName = item.second.name;
9090
cachedAddressTable.append(AddressTableEntry(addressType,
9191
QString::fromStdString(strName),
92-
QString::fromStdString(address.ToString())));
92+
QString::fromStdString(EncodeDestination(address))));
9393
}
9494
}
9595
// qLowerBound() and qUpperBound() require our cachedAddressTable list to be sorted in asc order
@@ -246,7 +246,7 @@ bool AddressTableModel::setData(const QModelIndex &index, const QVariant &value,
246246
if(role == Qt::EditRole)
247247
{
248248
LOCK(wallet->cs_wallet); /* For SetAddressBook / DelAddressBook */
249-
CTxDestination curAddress = CBitcoinAddress(rec->address.toStdString()).Get();
249+
CTxDestination curAddress = DecodeDestination(rec->address.toStdString());
250250
if(index.column() == Label)
251251
{
252252
// Do nothing, if old label == new label
@@ -257,7 +257,7 @@ bool AddressTableModel::setData(const QModelIndex &index, const QVariant &value,
257257
}
258258
wallet->SetAddressBook(curAddress, value.toString().toStdString(), strPurpose);
259259
} else if(index.column() == Address) {
260-
CTxDestination newAddress = CBitcoinAddress(value.toString().toStdString()).Get();
260+
CTxDestination newAddress = DecodeDestination(value.toString().toStdString());
261261
// Refuse to set invalid address, set error status and return false
262262
if(boost::get<CNoDestination>(&newAddress))
263263
{
@@ -358,7 +358,7 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con
358358
// Check for duplicate addresses
359359
{
360360
LOCK(wallet->cs_wallet);
361-
if(wallet->mapAddressBook.count(CBitcoinAddress(strAddress).Get()))
361+
if(wallet->mapAddressBook.count(DecodeDestination(strAddress)))
362362
{
363363
editStatus = DUPLICATE_ADDRESS;
364364
return QString();
@@ -384,7 +384,7 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con
384384
return QString();
385385
}
386386
}
387-
strAddress = CBitcoinAddress(newKey.GetID()).ToString();
387+
strAddress = EncodeDestination(newKey.GetID());
388388
}
389389
else
390390
{
@@ -394,7 +394,7 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con
394394
// Add entry
395395
{
396396
LOCK(wallet->cs_wallet);
397-
wallet->SetAddressBook(CBitcoinAddress(strAddress).Get(), strLabel,
397+
wallet->SetAddressBook(DecodeDestination(strAddress), strLabel,
398398
(type == Send ? "send" : "receive"));
399399
}
400400
return QString::fromStdString(strAddress);
@@ -412,7 +412,7 @@ bool AddressTableModel::removeRows(int row, int count, const QModelIndex &parent
412412
}
413413
{
414414
LOCK(wallet->cs_wallet);
415-
wallet->DelAddressBook(CBitcoinAddress(rec->address.toStdString()).Get());
415+
wallet->DelAddressBook(DecodeDestination(rec->address.toStdString()));
416416
}
417417
return true;
418418
}
@@ -423,8 +423,8 @@ QString AddressTableModel::labelForAddress(const QString &address) const
423423
{
424424
{
425425
LOCK(wallet->cs_wallet);
426-
CBitcoinAddress address_parsed(address.toStdString());
427-
std::map<CTxDestination, CAddressBookData>::iterator mi = wallet->mapAddressBook.find(address_parsed.Get());
426+
CTxDestination destination = DecodeDestination(address.toStdString());
427+
std::map<CTxDestination, CAddressBookData>::iterator mi = wallet->mapAddressBook.find(destination);
428428
if (mi != wallet->mapAddressBook.end())
429429
{
430430
return QString::fromStdString(mi->second.name);

src/qt/bitcoinaddressvalidator.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,9 @@ QValidator::State BitcoinAddressCheckValidator::validate(QString &input, int &po
8989
{
9090
Q_UNUSED(pos);
9191
// Validate the passed Bitcoin address
92-
CBitcoinAddress addr(input.toStdString());
93-
if (addr.IsValid())
92+
if (IsValidDestinationString(input.toStdString())) {
9493
return QValidator::Acceptable;
94+
}
9595

9696
return QValidator::Invalid;
9797
}

src/qt/coincontroldialog.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -660,7 +660,7 @@ void CoinControlDialog::updateView()
660660
QString sAddress = "";
661661
if(ExtractDestination(out.tx->tx->vout[out.i].scriptPubKey, outputAddress))
662662
{
663-
sAddress = QString::fromStdString(CBitcoinAddress(outputAddress).ToString());
663+
sAddress = QString::fromStdString(EncodeDestination(outputAddress));
664664

665665
// if listMode or change => show bitcoin address. In tree mode, address is not shown again for direct wallet address outputs
666666
if (!treeMode || (!(sAddress == sWalletAddress)))

src/qt/guiutil.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,9 @@ static std::string DummyAddress(const CChainParams &params)
112112
sourcedata.insert(sourcedata.end(), dummydata, dummydata + sizeof(dummydata));
113113
for(int i=0; i<256; ++i) { // Try every trailing byte
114114
std::string s = EncodeBase58(sourcedata.data(), sourcedata.data() + sourcedata.size());
115-
if (!CBitcoinAddress(s).IsValid())
115+
if (!IsValidDestinationString(s)) {
116116
return s;
117+
}
117118
sourcedata[sourcedata.size()-1] += 1;
118119
}
119120
return "";
@@ -248,7 +249,7 @@ QString formatBitcoinURI(const SendCoinsRecipient &info)
248249

249250
bool isDust(const QString& address, const CAmount& amount)
250251
{
251-
CTxDestination dest = CBitcoinAddress(address.toStdString()).Get();
252+
CTxDestination dest = DecodeDestination(address.toStdString());
252253
CScript script = GetScriptForDestination(dest);
253254
CTxOut txOut(amount, script);
254255
return IsDust(txOut, ::dustRelayFee);

src/qt/paymentserver.cpp

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -218,17 +218,15 @@ void PaymentServer::ipcParseCommandLine(int argc, char* argv[])
218218
SendCoinsRecipient r;
219219
if (GUIUtil::parseBitcoinURI(arg, &r) && !r.address.isEmpty())
220220
{
221-
CBitcoinAddress address(r.address.toStdString());
222221
auto tempChainParams = CreateChainParams(CBaseChainParams::MAIN);
223222

224-
if (address.IsValid(*tempChainParams))
225-
{
223+
if (IsValidDestinationString(r.address.toStdString(), *tempChainParams)) {
226224
SelectParams(CBaseChainParams::MAIN);
227-
}
228-
else {
225+
} else {
229226
tempChainParams = CreateChainParams(CBaseChainParams::TESTNET);
230-
if (address.IsValid(*tempChainParams))
227+
if (IsValidDestinationString(r.address.toStdString(), *tempChainParams)) {
231228
SelectParams(CBaseChainParams::TESTNET);
229+
}
232230
}
233231
}
234232
}
@@ -441,8 +439,7 @@ void PaymentServer::handleURIOrFile(const QString& s)
441439
SendCoinsRecipient recipient;
442440
if (GUIUtil::parseBitcoinURI(s, &recipient))
443441
{
444-
CBitcoinAddress address(recipient.address.toStdString());
445-
if (!address.IsValid()) {
442+
if (!IsValidDestinationString(recipient.address.toStdString())) {
446443
Q_EMIT message(tr("URI handling"), tr("Invalid payment address %1").arg(recipient.address),
447444
CClientUIInterface::MSG_ERROR);
448445
}
@@ -560,7 +557,7 @@ bool PaymentServer::processPaymentRequest(const PaymentRequestPlus& request, Sen
560557
CTxDestination dest;
561558
if (ExtractDestination(sendingTo.first, dest)) {
562559
// Append destination address
563-
addresses.append(QString::fromStdString(CBitcoinAddress(dest).ToString()));
560+
addresses.append(QString::fromStdString(EncodeDestination(dest)));
564561
}
565562
else if (!recipient.authenticatedMerchant.isEmpty()) {
566563
// Unauthenticated payment requests to custom bitcoin addresses are not supported

src/qt/sendcoinsdialog.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -777,19 +777,18 @@ void SendCoinsDialog::coinControlChangeEdited(const QString& text)
777777
CoinControlDialog::coinControl->destChange = CNoDestination();
778778
ui->labelCoinControlChangeLabel->setStyleSheet("QLabel{color:red;}");
779779

780-
CBitcoinAddress addr = CBitcoinAddress(text.toStdString());
780+
const CTxDestination dest = DecodeDestination(text.toStdString());
781781

782782
if (text.isEmpty()) // Nothing entered
783783
{
784784
ui->labelCoinControlChangeLabel->setText("");
785785
}
786-
else if (!addr.IsValid()) // Invalid address
786+
else if (!IsValidDestination(dest)) // Invalid address
787787
{
788788
ui->labelCoinControlChangeLabel->setText(tr("Warning: Invalid Bitcoin address"));
789789
}
790790
else // Valid address
791791
{
792-
const CTxDestination dest = addr.Get();
793792
if (!model->IsSpendable(dest)) {
794793
ui->labelCoinControlChangeLabel->setText(tr("Warning: Unknown change address"));
795794

0 commit comments

Comments
 (0)