Refactor: split CKeyID/CScriptID/CTxDestination from CBitcoinAddress

This introduces internal types:
* CKeyID: reference (hash160) of a key
* CScriptID: reference (hash160) of a script
* CTxDestination: a boost::variant of the former two

CBitcoinAddress is retrofitted to be a Base58 encoding of a
CTxDestination. This allows all internal code to only use the
internal types, and only have RPC and GUI depend on the base58 code.

Furthermore, the header dependencies are a lot saner now. base58.h is
at the top (right below rpc and gui) instead of at the bottom. For the
rest: wallet -> script -> keystore -> key. Only keystore still requires
a forward declaration of CScript. Solving that would require splitting
script into two layers.
This commit is contained in:
Pieter Wuille
2012-05-14 23:44:52 +02:00
parent fd61d6f506
commit 1025440184
26 changed files with 477 additions and 339 deletions

View File

@@ -3,6 +3,7 @@
#include "walletmodel.h"
#include "wallet.h"
#include "base58.h"
#include <QFont>
#include <QColor>
@@ -58,11 +59,11 @@ public:
cachedAddressTable.clear();
{
LOCK(wallet->cs_wallet);
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, std::string)& item, wallet->mapAddressBook)
BOOST_FOREACH(const PAIRTYPE(CTxDestination, std::string)& item, wallet->mapAddressBook)
{
const CBitcoinAddress& address = item.first;
const std::string& strName = item.second;
bool fMine = wallet->HaveKey(address);
bool fMine = IsMine(*wallet, address.Get());
cachedAddressTable.append(AddressTableEntry(fMine ? AddressTableEntry::Receiving : AddressTableEntry::Sending,
QString::fromStdString(strName),
QString::fromStdString(address.ToString())));
@@ -220,7 +221,8 @@ bool AddressTableModel::setData(const QModelIndex & index, const QVariant & valu
switch(index.column())
{
case Label:
wallet->SetAddressBookName(rec->address.toStdString(), value.toString().toStdString());
wallet->SetAddressBookName(CBitcoinAddress(rec->address.toStdString()).Get(), value.toString().toStdString());
rec->label = value.toString();
break;
case Address:
// Refuse to set invalid address, set error status and return false
@@ -235,9 +237,9 @@ bool AddressTableModel::setData(const QModelIndex & index, const QVariant & valu
{
LOCK(wallet->cs_wallet);
// Remove old entry
wallet->DelAddressBookName(rec->address.toStdString());
wallet->DelAddressBookName(CBitcoinAddress(rec->address.toStdString()).Get());
// Add new entry with new address
wallet->SetAddressBookName(value.toString().toStdString(), rec->label.toStdString());
wallet->SetAddressBookName(CBitcoinAddress(value.toString().toStdString()).Get(), rec->label.toStdString());
}
}
break;
@@ -314,7 +316,7 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con
// Check for duplicate addresses
{
LOCK(wallet->cs_wallet);
if(wallet->mapAddressBook.count(strAddress))
if(wallet->mapAddressBook.count(CBitcoinAddress(strAddress).Get()))
{
editStatus = DUPLICATE_ADDRESS;
return QString();
@@ -337,7 +339,7 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con
editStatus = KEY_GENERATION_FAILURE;
return QString();
}
strAddress = CBitcoinAddress(newKey).ToString();
strAddress = CBitcoinAddress(newKey.GetID()).ToString();
}
else
{
@@ -346,7 +348,7 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con
// Add entry
{
LOCK(wallet->cs_wallet);
wallet->SetAddressBookName(strAddress, strLabel);
wallet->SetAddressBookName(CBitcoinAddress(strAddress).Get(), strLabel);
}
return QString::fromStdString(strAddress);
}
@@ -363,7 +365,7 @@ bool AddressTableModel::removeRows(int row, int count, const QModelIndex & paren
}
{
LOCK(wallet->cs_wallet);
wallet->DelAddressBookName(rec->address.toStdString());
wallet->DelAddressBookName(CBitcoinAddress(rec->address.toStdString()).Get());
}
return true;
}
@@ -375,7 +377,7 @@ QString AddressTableModel::labelForAddress(const QString &address) const
{
LOCK(wallet->cs_wallet);
CBitcoinAddress address_parsed(address.toStdString());
std::map<CBitcoinAddress, std::string>::iterator mi = wallet->mapAddressBook.find(address_parsed);
std::map<CTxDestination, std::string>::iterator mi = wallet->mapAddressBook.find(address_parsed.Get());
if (mi != wallet->mapAddressBook.end())
{
return QString::fromStdString(mi->second);

View File

@@ -10,6 +10,7 @@
#include "main.h"
#include "wallet.h"
#include "init.h"
#include "base58.h"
#include "messagepage.h"
#include "ui_messagepage.h"
@@ -83,6 +84,13 @@ void MessagePage::on_signMessage_clicked()
QMessageBox::Abort, QMessageBox::Abort);
return;
}
CKeyID keyID;
if (!addr.GetKeyID(keyID))
{
QMessageBox::critical(this, tr("Error signing"), tr("%1 does not refer to a key.").arg(address),
QMessageBox::Abort, QMessageBox::Abort);
return;
}
WalletModel::UnlockContext ctx(model->requestUnlock());
if(!ctx.isValid())
@@ -92,7 +100,7 @@ void MessagePage::on_signMessage_clicked()
}
CKey key;
if (!pwalletMain->GetKey(addr, key))
if (!pwalletMain->GetKey(keyID, key))
{
QMessageBox::critical(this, tr("Error signing"), tr("Private key for %1 is not available.").arg(address),
QMessageBox::Abort, QMessageBox::Abort);

View File

@@ -7,6 +7,7 @@
#include "wallet.h"
#include "db.h"
#include "ui_interface.h"
#include "base58.h"
#include <QString>
@@ -85,14 +86,14 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
{
if (wallet->IsMine(txout))
{
CBitcoinAddress address;
if (ExtractAddress(txout.scriptPubKey, address) && wallet->HaveKey(address))
CTxDestination address;
if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address))
{
if (wallet->mapAddressBook.count(address))
{
strHTML += tr("<b>From:</b> ") + tr("unknown") + "<br>";
strHTML += tr("<b>To:</b> ");
strHTML += GUIUtil::HtmlEscape(address.ToString());
strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString());
if (!wallet->mapAddressBook[address].empty())
strHTML += tr(" (yours, label: ") + GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + ")";
else
@@ -115,8 +116,9 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
// Online transaction
strAddress = wtx.mapValue["to"];
strHTML += tr("<b>To:</b> ");
if (wallet->mapAddressBook.count(strAddress) && !wallet->mapAddressBook[strAddress].empty())
strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[strAddress]) + " ";
CTxDestination dest = CBitcoinAddress(strAddress).Get();
if (wallet->mapAddressBook.count(dest) && !wallet->mapAddressBook[dest].empty())
strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[dest]) + " ";
strHTML += GUIUtil::HtmlEscape(strAddress) + "<br>";
}
@@ -170,13 +172,13 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
if (wtx.mapValue["to"].empty())
{
// Offline transaction
CBitcoinAddress address;
if (ExtractAddress(txout.scriptPubKey, address))
CTxDestination address;
if (ExtractDestination(txout.scriptPubKey, address))
{
strHTML += tr("<b>To:</b> ");
if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].empty())
strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + " ";
strHTML += GUIUtil::HtmlEscape(address.ToString());
strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString());
strHTML += "<br>";
}
}
@@ -260,12 +262,12 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
{
strHTML += "<li>";
const CTxOut &vout = prev.vout[prevout.n];
CBitcoinAddress address;
if (ExtractAddress(vout.scriptPubKey, address))
CTxDestination address;
if (ExtractDestination(vout.scriptPubKey, address))
{
if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].empty())
strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + " ";
strHTML += QString::fromStdString(address.ToString());
strHTML += QString::fromStdString(CBitcoinAddress(address).ToString());
}
strHTML = strHTML + " Amount=" + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC,vout.nValue);
strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) ? "true" : "false") + "</li>";

View File

@@ -1,6 +1,7 @@
#include "transactionrecord.h"
#include "wallet.h"
#include "base58.h"
/* Return positive answer if transaction should be shown in list.
*/
@@ -50,7 +51,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
if(wallet->IsMine(txout))
{
TransactionRecord sub(hash, nTime);
CBitcoinAddress address;
CTxDestination address;
sub.idx = parts.size(); // sequence number
sub.credit = txout.nValue;
if (wtx.IsCoinBase())
@@ -58,11 +59,11 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
// Generated
sub.type = TransactionRecord::Generated;
}
else if (ExtractAddress(txout.scriptPubKey, address) && wallet->HaveKey(address))
else if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address))
{
// Received by Bitcoin Address
sub.type = TransactionRecord::RecvWithAddress;
sub.address = address.ToString();
sub.address = CBitcoinAddress(address).ToString();
}
else
{
@@ -113,12 +114,12 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
continue;
}
CBitcoinAddress address;
if (ExtractAddress(txout.scriptPubKey, address))
CTxDestination address;
if (ExtractDestination(txout.scriptPubKey, address))
{
// Sent to Bitcoin Address
sub.type = TransactionRecord::SendToAddress;
sub.address = address.ToString();
sub.address = CBitcoinAddress(address).ToString();
}
else
{

View File

@@ -14,6 +14,7 @@
#include "walletmodel.h"
#include "addresstablemodel.h"
#include "guiutil.h"
#include "base58.h"
VerifyMessageDialog::VerifyMessageDialog(AddressTableModel *addressModel, QWidget *parent) :
QDialog(parent),
@@ -62,7 +63,7 @@ bool VerifyMessageDialog::checkAddress()
return false;
}
CBitcoinAddress address(key.GetPubKey());
CBitcoinAddress address(key.GetPubKey().GetID());
QString qStringAddress = QString::fromStdString(address.ToString());
ui->lnAddress->setText(qStringAddress);
ui->copyToClipboard->setEnabled(true);

View File

@@ -7,6 +7,7 @@
#include "ui_interface.h"
#include "wallet.h"
#include "walletdb.h" // for BackupWallet
#include "base58.h"
#include <QSet>
@@ -137,7 +138,7 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(const QList<SendCoinsRecipie
foreach(const SendCoinsRecipient &rcp, recipients)
{
CScript scriptPubKey;
scriptPubKey.SetBitcoinAddress(rcp.address.toStdString());
scriptPubKey.SetDestination(CBitcoinAddress(rcp.address.toStdString()).Get());
vecSend.push_back(make_pair(scriptPubKey, rcp.amount));
}
@@ -169,16 +170,17 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(const QList<SendCoinsRecipie
foreach(const SendCoinsRecipient &rcp, recipients)
{
std::string strAddress = rcp.address.toStdString();
CTxDestination dest = CBitcoinAddress(strAddress).Get();
std::string strLabel = rcp.label.toStdString();
{
LOCK(wallet->cs_wallet);
std::map<CBitcoinAddress, std::string>::iterator mi = wallet->mapAddressBook.find(strAddress);
std::map<CTxDestination, std::string>::iterator mi = wallet->mapAddressBook.find(dest);
// Check if we have a new address or an updated label
if (mi == wallet->mapAddressBook.end() || mi->second != strLabel)
{
wallet->SetAddressBookName(strAddress, strLabel);
wallet->SetAddressBookName(dest, strLabel);
}
}
}
@@ -268,11 +270,11 @@ static void NotifyKeyStoreStatusChanged(WalletModel *walletmodel, CCryptoKeyStor
QMetaObject::invokeMethod(walletmodel, "updateStatus", Qt::QueuedConnection);
}
static void NotifyAddressBookChanged(WalletModel *walletmodel, CWallet *wallet, const std::string &address, const std::string &label, bool isMine, ChangeType status)
static void NotifyAddressBookChanged(WalletModel *walletmodel, CWallet *wallet, const CTxDestination &address, const std::string &label, bool isMine, ChangeType status)
{
OutputDebugStringF("NotifyAddressBookChanged %s %s isMine=%i status=%i\n", address.c_str(), label.c_str(), isMine, status);
OutputDebugStringF("NotifyAddressBookChanged %s %s isMine=%i status=%i\n", CBitcoinAddress(address).ToString().c_str(), label.c_str(), isMine, status);
QMetaObject::invokeMethod(walletmodel, "updateAddressBook", Qt::QueuedConnection,
Q_ARG(QString, QString::fromStdString(address)),
Q_ARG(QString, QString::fromStdString(CBitcoinAddress(address).ToString())),
Q_ARG(QString, QString::fromStdString(label)),
Q_ARG(bool, isMine),
Q_ARG(int, status));