Browse Source

Create new zaddrs at run-time for new HushContacts

This shows how to generate a zaddr at run-time and use it correctly,
I am sure Denio will be happy! This method will work for Sietch in SDL,
but actually I need to throw all this code away for this exact use case.
At least Denio can use it!

What I did was to study how the code to generate new zaddrs in the Receive
UI works, and this is the TLDR: It uses a chain of callbacks to assure that
class-level data it stores (the RPC::zaddresses variable) always has data
when it goes to read it. I did the lazy thing and pushed everything into
a single callback, which is equivalent.

The core problem now is that a brand new zaddr will not have any funds,
and is unable to pay the default tx fee. We must always make sure we have a
pool of these addresses, at startup, and make sure they have some funds,
which can be periodically checked and "topped up". Once we have that,
we will pull a new address from that pool if we add a new HushContact, instead
of this current run-time generation of a new zaddr.
chat
Duke Leto 4 years ago
parent
commit
5496ae4e41
  1. 7
      src/addressbook.cpp
  2. 157
      src/mainwindow.cpp
  3. 2
      src/mainwindow.h

7
src/addressbook.cpp

@ -327,9 +327,14 @@ QString AddressBook::writeableFile() {
// Add a new address/label to the database
// TODO: return bool for success/fail
void AddressBook::addAddressLabel(QString label, QString address, QString myzaddr) {
qDebug() << "Adding " << label << "=" << address << "," << myzaddr;
Q_ASSERT(Settings::isValidAddress(address));
if(!Settings::isValidAddress(address)) {
qDebug() << "Invalid zaddr:" << address;
//return;
}
// First, remove any existing label
// Iterate over the list and remove the label/address

157
src/mainwindow.cpp

@ -181,6 +181,7 @@ QString MainWindow::createHeaderMemo(QString cid, QString zaddr, int version=0,
QString header="";
QJsonDocument j;
QJsonObject h;
version = -1; // This is unstable v=-1 until we launch with v=0
// We use short keynames to use less space for metadata and so allow
// the user to send more actual data in memos
h["h"] = headerNumber; // header number
@ -196,36 +197,8 @@ QString MainWindow::createHeaderMemo(QString cid, QString zaddr, int version=0,
return header;
}
// Send button clicked
void MainWindow::sendMemo() {
Tx tx;
tx.fee = Settings::getMinerFee();
// TODO: choose current zaddr for this contact
HushChat chat = MainWindow::getHushChat();
HushContact contact = chat.getContact();
//TODO: verify we currently own the private key to this zaddr via z_validateaddress
tx.fromAddr = contact.getMyZaddr();
if(tx.fromAddr.isEmpty()) {
// Either we made a custom zaddr for this contact in the past, or we make a new one now
QString newzaddr;
rpc->newZaddr( [=] (json reply) {
QString z = QString::fromStdString(reply.get<json::string_t>());
qDebug() << "created new myZaddr="<< z;
// TODO: bullshit error about const objects
// contact.setMyZaddr(z);
});
//TODO: race condition in setting/getting new contact zaddr?
AddressBook::getInstance()->addAddressLabel(contact.getName(), contact.getZaddr(), contact.getMyZaddr() );
qDebug() << "Wrote new myZaddr for " << contact.getName() << " to storage";
}
qDebug() << "Using " << tx.fromAddr << " as from address for " << contact.getName();
double amount = 0;
QString cid = QUuid::createUuid().toString(QUuid::WithoutBraces);
QString hmemo = createHeaderMemo(cid,contact.getMyZaddr());
QString memo = ui->textEdit->toPlainText();
QString addr = contact.getZaddr();
QString MainWindow::getZaddrForCurrentContact() {
QString zaddr;
QModelIndex qmi = ui->contactsView->currentIndex();
if (qmi.isValid()) {
qDebug() << "Current (row,col) index: " << qmi.row() << "," << qmi.column();
@ -233,50 +206,102 @@ void MainWindow::sendMemo() {
QMap <int, QVariant> currentContacts = ui->contactsView->model()->itemData(qmi);
QString contact = currentContacts[0].toString();
qDebug() << "Current HushContact: " << contact;
addr = getZaddrForContact(contact);
zaddr = getZaddrForContact(contact);
} else {
qDebug() << "Invalid current index, no contacts selected";
}
return zaddr;
}
// we send a header memo plus actual memo
tx.toAddrs.push_back( ToFields{addr, amount, hmemo, hmemo.toUtf8().toHex()} );
tx.toAddrs.push_back( ToFields{addr, amount, memo, memo.toUtf8().toHex()} );
qDebug() << "Sending "<< addr << " a memo: " << memo;
QString error = doSendTxValidations(tx);
if (!error.isEmpty()) {
// Something went wrong, so show an error and exit
QMessageBox msg(QMessageBox::Critical, tr("Transaction Error"), error,
QMessageBox::Ok, this);
QString MainWindow::getNameForCurrentContact() {
QString name;
QModelIndex qmi = ui->contactsView->currentIndex();
if (qmi.isValid()) {
qDebug() << "Current (row,col) index: " << qmi.row() << "," << qmi.column();
// we seem to get duplicates due to QT internals shenanigans, just pick the first
QMap <int, QVariant> currentContacts = ui->contactsView->model()->itemData(qmi);
QString name = currentContacts[0].toString();
} else {
qDebug() << "Invalid current index, no contacts selected";
}
return name;
}
msg.exec();
// Send button clicked
void MainWindow::sendMemo() {
HushChat thisChat = MainWindow::getHushChat();
// abort the Tx
return;
}
// Either we made a custom zaddr for this contact in the past, or we make a new one now
if(thisChat.getContact().getMyZaddr().isEmpty()) {
QString newzaddr;
rpc->newZaddr( [=] (json reply) {
Tx tx;
tx.fee = Settings::getMinerFee();
//TODO: verify we currently own the private key to this zaddr via z_validateaddress
HushChat chat = MainWindow::getHushChat();
HushContact contact = chat.getContact();
QString myZaddr = QString::fromStdString(reply.get<json::string_t>());
QString addr = getZaddrForCurrentContact();
QString name = getNameForCurrentContact();
qDebug() << "created new myZaddr="<< myZaddr << " for " << name;
contact.setName(name);
contact.setMyZaddr(myZaddr);
contact.setZaddr(addr);
AddressBook::getInstance()->addAddressLabel(contact.getName(), contact.getZaddr(), contact.getMyZaddr());
qDebug() << "Wrote new myZaddr for " << contact.getName() << " to storage";
qDebug() << "Using " << myZaddr << " as from address for " << contact.getName();
double amount = 0;
QString cid = QUuid::createUuid().toString(QUuid::WithoutBraces);
QString hmemo = createHeaderMemo(cid,myZaddr);
QString memo = ui->textEdit->toPlainText();
// we send a header memo plus actual memo
tx.toAddrs.push_back( ToFields{addr, amount, hmemo, hmemo.toUtf8().toHex()} );
tx.toAddrs.push_back( ToFields{addr, amount, memo, memo.toUtf8().toHex()} );
tx.fromAddr = contact.getMyZaddr();
qDebug() << "Sending "<< name << "(" << addr << ") a memo: " << memo;
QString error = doSendTxValidations(tx);
if (!error.isEmpty()) {
// Something went wrong, so show an error and exit
QMessageBox msg(QMessageBox::Critical, tr("Transaction Error"), error,
QMessageBox::Ok, this);
msg.exec();
// abort the Tx
return;
}
// Show a dialog to confirm the Tx
if (confirmTx(tx)) {
// And send the Tx
rpc->executeTransaction(tx,
[=] (QString opid) {
ui->statusBar->showMessage(tr("Computing transaction: ") % opid);
qDebug() << "Computing opid: " << opid;
},
[=] (QString, QString txid) {
ui->statusBar->showMessage(Settings::txidStatusMessage + " " + txid);
},
[=] (QString opid, QString errStr) {
ui->statusBar->showMessage(QObject::tr(" Transaction ") % opid % QObject::tr(" failed"), 15 * 1000);
if (!opid.isEmpty())
errStr = QObject::tr("The transaction with id ") % opid % QObject::tr(" failed. The error was") + ":\n\n" + errStr;
QMessageBox::critical(this, QObject::tr("Transaction Error"), errStr, QMessageBox::Ok);
// Show a dialog to confirm the Tx
if (confirmTx(tx)) {
// And send the Tx
rpc->executeTransaction(tx,
[=] (QString opid) {
ui->statusBar->showMessage(tr("Computing transaction: ") % opid);
qDebug() << "Computing opid: " << opid;
},
[=] (QString, QString txid) {
ui->statusBar->showMessage(Settings::txidStatusMessage + " " + txid);
},
[=] (QString opid, QString errStr) {
ui->statusBar->showMessage(QObject::tr(" Transaction ") % opid % QObject::tr(" failed"), 15 * 1000);
if (!opid.isEmpty())
errStr = QObject::tr("The transaction with id ") % opid % QObject::tr(" failed. The error was") + ":\n\n" + errStr;
QMessageBox::critical(this, QObject::tr("Transaction Error"), errStr, QMessageBox::Ok);
}
);
}
);
}
}); // newZaddr
} else {
// this contact already has a myZaddr
}
}
void MainWindow::createWebsocket(QString wormholecode) {

2
src/mainwindow.h

@ -81,6 +81,8 @@ public:
QRegExpValidator* getAmountValidator() { return amtValidator; }
QString getZaddrForContact(QString contact);
QString getZaddrForCurrentContact();
QString getNameForCurrentContact();
QString doSendTxValidations(Tx tx);
void setDefaultPayFrom();

Loading…
Cancel
Save