Browse Source

simple working

recurring
Aditya Kulkarni 6 years ago
parent
commit
9268574588
  1. 17
      src/mainwindow.cpp
  2. 8
      src/rpc.cpp
  3. 8
      src/rpc.h
  4. 78
      src/turnstile.cpp
  5. 1
      src/turnstile.h

17
src/mainwindow.cpp

@ -8,6 +8,7 @@
#include "balancestablemodel.h" #include "balancestablemodel.h"
#include "settings.h" #include "settings.h"
#include "utils.h" #include "utils.h"
#import "turnstile.h"
#include "senttxstore.h" #include "senttxstore.h"
#include "precompiled.h" #include "precompiled.h"
@ -83,7 +84,7 @@ void MainWindow::setupTurnstileDialog() {
QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation); QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation);
turnstile.msgIcon->setPixmap(icon.pixmap(64, 64)); turnstile.msgIcon->setPixmap(icon.pixmap(64, 64));
auto getAllSproutBalance = [=] () { auto fnGetAllSproutBalance = [=] () {
double bal = 0; double bal = 0;
for (auto addr : *rpc->getAllZAddresses()) { for (auto addr : *rpc->getAllZAddresses()) {
if (Settings::getInstance()->isSproutAddress(addr)) { if (Settings::getInstance()->isSproutAddress(addr)) {
@ -95,19 +96,20 @@ void MainWindow::setupTurnstileDialog() {
}; };
turnstile.migrateZaddList->addItem("All Sprout z-Addrs"); turnstile.migrateZaddList->addItem("All Sprout z-Addrs");
turnstile.fromBalance->setText(Settings::getInstance()->getZECUSDDisplayFormat(getAllSproutBalance())); turnstile.fromBalance->setText(Settings::getInstance()->getZECUSDDisplayFormat(fnGetAllSproutBalance()));
for (auto addr : *rpc->getAllZAddresses()) { for (auto addr : *rpc->getAllZAddresses()) {
if (Settings::getInstance()->isSaplingAddress(addr)) { if (Settings::getInstance()->isSaplingAddress(addr)) {
turnstile.migrateTo->addItem(addr); turnstile.migrateTo->addItem(addr);
} else { } else {
turnstile.migrateZaddList->addItem(addr); if (rpc->getAllBalances()->value(addr) > 0)
turnstile.migrateZaddList->addItem(addr);
} }
} }
QObject::connect(turnstile.migrateZaddList, &QComboBox::currentTextChanged, [=] (auto addr) { QObject::connect(turnstile.migrateZaddList, &QComboBox::currentTextChanged, [=] (auto addr) {
double bal = 0; double bal = 0;
if (addr.startsWith("All")) { if (addr.startsWith("All")) {
bal = getAllSproutBalance(); bal = fnGetAllSproutBalance();
} else { } else {
bal = rpc->getAllBalances()->value(addr); bal = rpc->getAllBalances()->value(addr);
} }
@ -121,11 +123,12 @@ void MainWindow::setupTurnstileDialog() {
turnstile.buttonBox->button(QDialogButtonBox::Ok)->setText("Start"); turnstile.buttonBox->button(QDialogButtonBox::Ok)->setText("Start");
d.exec(); if (d.exec() == QDialog::Accepted) {
rpc->getTurnstile()->planMigration(
turnstile.migrateZaddList->currentText(), turnstile.migrateTo->currentText());
}
}); });
QObject::connect(ui->actionProgress, &QAction::triggered, [=] () { QObject::connect(ui->actionProgress, &QAction::triggered, [=] () {
Ui_TurnstileProgress progress; Ui_TurnstileProgress progress;
QDialog d(this); QDialog d(this);

8
src/rpc.cpp

@ -11,6 +11,8 @@ RPC::RPC(QNetworkAccessManager* client, MainWindow* main) {
this->main = main; this->main = main;
this->ui = main->ui; this->ui = main->ui;
this->turnstile = new Turnstile(this);
// Setup balances table model // Setup balances table model
balancesTableModel = new BalancesTableModel(main->ui->balancesTable); balancesTableModel = new BalancesTableModel(main->ui->balancesTable);
main->ui->balancesTable->setModel(balancesTableModel); main->ui->balancesTable->setModel(balancesTableModel);
@ -56,6 +58,7 @@ RPC::~RPC() {
delete transactionsTableModel; delete transactionsTableModel;
delete balancesTableModel; delete balancesTableModel;
delete turnstile;
delete utxos; delete utxos;
delete allBalances; delete allBalances;
@ -300,7 +303,7 @@ void RPC::fillTxJsonParams(json& params, Tx tx) {
// Construct the JSON params // Construct the JSON params
json rec = json::object(); json rec = json::object();
rec["address"] = toAddr.addr.toStdString(); rec["address"] = toAddr.addr.toStdString();
rec["amount"] = toAddr.amount; rec["amount"] = QString::number(toAddr.amount, 'f', 8).toDouble(); // Force it through string for rounding
if (toAddr.addr.startsWith("z") && !toAddr.encodedMemo.trimmed().isEmpty()) if (toAddr.addr.startsWith("z") && !toAddr.encodedMemo.trimmed().isEmpty())
rec["memo"] = toAddr.encodedMemo.toStdString(); rec["memo"] = toAddr.encodedMemo.toStdString();
@ -487,6 +490,9 @@ void RPC::refreshAddresses() {
// Function to create the data model and update the views, used below. // Function to create the data model and update the views, used below.
void RPC::updateUI(bool anyUnconfirmed) { void RPC::updateUI(bool anyUnconfirmed) {
// See if the turnstile migration has any steps that need to be done.
turnstile->executeMigrationStep();
ui->unconfirmedWarning->setVisible(anyUnconfirmed); ui->unconfirmedWarning->setVisible(anyUnconfirmed);
// Update balances model data, which will update the table too // Update balances model data, which will update the table too

8
src/rpc.h

@ -11,6 +11,7 @@
using json = nlohmann::json; using json = nlohmann::json;
class Turnstile;
struct TransactionItem { struct TransactionItem {
QString type; QString type;
@ -44,8 +45,10 @@ public:
void reloadConnectionInfo(); void reloadConnectionInfo();
void newZaddr (bool sapling, const std::function<void(json)>& cb); void newZaddr(bool sapling, const std::function<void(json)>& cb);
void newTaddr (const std::function<void(json)>& cb); void newTaddr(const std::function<void(json)>& cb);
Turnstile* getTurnstile() { return turnstile; }
// Batch method. Note: Because of the template, it has to be in the header file. // Batch method. Note: Because of the template, it has to be in the header file.
template<class T> template<class T>
@ -139,6 +142,7 @@ private:
Ui::MainWindow* ui; Ui::MainWindow* ui;
MainWindow* main; MainWindow* main;
Turnstile* turnstile;
// Current balance in the UI. If this number updates, then refresh the UI // Current balance in the UI. If this number updates, then refresh the UI
QString currentBalance; QString currentBalance;

78
src/turnstile.cpp

@ -1,5 +1,6 @@
#include "turnstile.h" #include "turnstile.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "unspentoutput.h"
#include "rpc.h" #include "rpc.h"
#include "utils.h" #include "utils.h"
#include "settings.h" #include "settings.h"
@ -18,7 +19,7 @@ Turnstile::~Turnstile() {
void printPlan(QList<TurnstileMigrationItem> plan) { void printPlan(QList<TurnstileMigrationItem> plan) {
for (auto item : plan) { for (auto item : plan) {
qDebug() << item.fromAddr << item.intTAddr qDebug() << item.fromAddr << item.intTAddr
<< item.destAddr << item.amount << item.blockNumber << item.chaff << item.status; << item.destAddr << item.amount << item.blockNumber << item.status;
} }
} }
@ -39,13 +40,13 @@ QString Turnstile::writeableFile() {
// Data stream write/read methods for migration items // Data stream write/read methods for migration items
QDataStream &operator<<(QDataStream& ds, const TurnstileMigrationItem& item) { QDataStream &operator<<(QDataStream& ds, const TurnstileMigrationItem& item) {
return ds << QString("v1") << item.fromAddr << item.intTAddr return ds << QString("v1") << item.fromAddr << item.intTAddr
<< item.destAddr << item.amount << item.blockNumber << item.chaff << item.status; << item.destAddr << item.amount << item.blockNumber << item.status;
} }
QDataStream &operator>>(QDataStream& ds, TurnstileMigrationItem& item) { QDataStream &operator>>(QDataStream& ds, TurnstileMigrationItem& item) {
QString version; QString version;
return ds >> version >> item.fromAddr >> item.intTAddr return ds >> version >> item.fromAddr >> item.intTAddr
>> item.destAddr >> item.amount >> item.blockNumber >> item.chaff >> item.status; >> item.destAddr >> item.amount >> item.blockNumber >> item.status;
} }
void Turnstile::writeMigrationPlan(QList<TurnstileMigrationItem> plan) { void Turnstile::writeMigrationPlan(QList<TurnstileMigrationItem> plan) {
@ -105,19 +106,19 @@ void Turnstile::planMigration(QString zaddr, QString destAddr) {
for (int i=0; i < splits.size(); i++) { for (int i=0; i < splits.size(); i++) {
auto tAddr = newAddrs->values()[i].get<json::string_t>(); auto tAddr = newAddrs->values()[i].get<json::string_t>();
auto item = TurnstileMigrationItem { zaddr, QString::fromStdString(tAddr), destAddr, auto item = TurnstileMigrationItem { zaddr, QString::fromStdString(tAddr), destAddr,
blockNumbers[i], splits[i], i == splits.size() -1, blockNumbers[i], splits[i],
TurnstileMigrationItemStatus::NotStarted }; TurnstileMigrationItemStatus::NotStarted };
migItems.push_back(item); migItems.push_back(item);
} }
std::sort(migItems.begin(), migItems.end(), [&] (auto a, auto b) {
return a.blockNumber < b.blockNumber;
});
// The first migration is shifted to the current block, so the user sees something // The first migration is shifted to the current block, so the user sees something
// happening immediately // happening immediately
migItems[0].blockNumber = curBlock; migItems[0].blockNumber = curBlock;
std::sort(migItems.begin(), migItems.end(), [&] (auto a, auto b) {
return a.blockNumber < b.blockNumber;
});
writeMigrationPlan(migItems); writeMigrationPlan(migItems);
auto readPlan = readMigrationPlan(); auto readPlan = readMigrationPlan();
} }
@ -149,6 +150,9 @@ QList<double> Turnstile::splitAmount(double amount, int parts) {
for (auto a : amounts) { for (auto a : amounts) {
sumofparts += a; sumofparts += a;
} }
// Add the Tx fees
sumofparts += amounts.size() * Utils::getMinerFee();
Q_ASSERT(sumofparts == amount); Q_ASSERT(sumofparts == amount);
return amounts; return amounts;
@ -163,18 +167,10 @@ void Turnstile::fillAmounts(QList<double>& amounts, double amount, int count) {
// Get the rounded value to 4 decimal places (approx $0.01) // Get the rounded value to 4 decimal places (approx $0.01)
double actual = std::floor(amount * 10000) / 10000; double actual = std::floor(amount * 10000) / 10000;
// Reduce the Dev Tx fee from the amount
actual = actual - 0.0001; //Utils::getDevFee();
// Also account for the fees needed to send all these transactions // Also account for the fees needed to send all these transactions
actual = actual - (Utils::getMinerFee() * (amounts.size() + 1)); actual = actual - (Utils::getMinerFee() * (amounts.size() + 1));
// Calculate the chaff.
double chaff = amount - actual;
amounts.push_back(actual); amounts.push_back(actual);
if (chaff > 0.00000001) // zcash is split down to 8 decimal places
amounts.push_back(chaff);
return; return;
} }
@ -182,6 +178,7 @@ void Turnstile::fillAmounts(QList<double>& amounts, double amount, int count) {
auto curAmount = std::rand() % (int)std::floor(amount); auto curAmount = std::rand() % (int)std::floor(amount);
// Try to round it off // Try to round it off
// TODO: Do this via log
if (curAmount > 1000) { if (curAmount > 1000) {
curAmount = std::floor(curAmount / 100) * 100; curAmount = std::floor(curAmount / 100) * 100;
} else if (curAmount > 100) { } else if (curAmount > 100) {
@ -201,21 +198,30 @@ void Turnstile::executeMigrationStep() {
printPlan(plan); printPlan(plan);
// Get to the next unexecuted step // Get to the next unexecuted step
auto eligibleItem = [&] (auto item) { auto fnIsEligibleItem = [&] (auto item) {
return !item.chaff && return item.status == TurnstileMigrationItemStatus::NotStarted ||
(item.status == TurnstileMigrationItemStatus::NotStarted || item.status == TurnstileMigrationItemStatus::SentToT;
item.status == TurnstileMigrationItemStatus::SentToT); };
// Fn to find if there are any unconfirmed funds for this address.
auto fnHasUnconfirmed = [=] (QString addr) {
auto utxoset = rpc->getUTXOs();
return std::find_if(utxoset->begin(), utxoset->end(), [=] (auto utxo) {
return utxo.address == addr && utxo.confirmations == 0;
}) != utxoset->end();
}; };
auto nextStep = std::find_if(plan.begin(), plan.end(), eligibleItem);
if (nextStep == plan.end()) return; // Nothing to do // Find the next step
qDebug() << nextStep->blockNumber << ":" << Settings::getInstance()->getBlockNumber(); auto nextStep = std::find_if(plan.begin(), plan.end(), fnIsEligibleItem);
if (nextStep->blockNumber > Settings::getInstance()->getBlockNumber()) return;
if (nextStep == plan.end())
return; // Nothing to do
if (nextStep->blockNumber > Settings::getInstance()->getBlockNumber())
return;
// Is this the last step for this address? // Is this the last step for this address?
auto lastStep = std::find_if(std::next(nextStep), plan.end(), [&] (auto item) { auto lastStep = std::find_if(std::next(nextStep), plan.end(), fnIsEligibleItem) == plan.end();
return item.fromAddr == nextStep->fromAddr && eligibleItem(item);
}) == plan.end();
// Execute this step // Execute this step
if (nextStep->status == TurnstileMigrationItemStatus::NotStarted) { if (nextStep->status == TurnstileMigrationItemStatus::NotStarted) {
@ -228,19 +234,18 @@ void Turnstile::executeMigrationStep() {
return; return;
} }
QList<ToFields> to = { ToFields{ nextStep->intTAddr, nextStep->amount, "", "" } }; auto to = ToFields{ nextStep->intTAddr, nextStep->amount, "", "" };
// If this is the last step, then add chaff and the dev fee to the tx // If this is the last step, then send the remaining amount instead of the actual amount.
if (lastStep) { if (lastStep) {
auto remainingAmount = balance - nextStep->amount; auto remainingAmount = balance - Utils::getMinerFee();
if (remainingAmount > 0) { if (remainingAmount > 0) {
auto devFee = ToFields{ Utils::getDevSproutAddr(), remainingAmount, "", "" }; to.amount = remainingAmount;
to.push_back(devFee);
} }
} }
// Create the Tx // Create the Tx
auto tx = Tx{ nextStep->fromAddr, to, Utils::getMinerFee() }; auto tx = Tx{ nextStep->fromAddr, { to }, Utils::getMinerFee() };
// And send it // And send it
doSendTx(tx, [=] () { doSendTx(tx, [=] () {
@ -250,6 +255,12 @@ void Turnstile::executeMigrationStep() {
}); });
} else if (nextStep->status == TurnstileMigrationItemStatus::SentToT) { } else if (nextStep->status == TurnstileMigrationItemStatus::SentToT) {
// First thing to do is check to see if the funds are confirmed.
if (fnHasUnconfirmed(nextStep->intTAddr)) {
qDebug() << QString("unconfirmed, waiting");
return;
}
// Send it to the final destination address. // Send it to the final destination address.
auto bal = rpc->getAllBalances()->value(nextStep->intTAddr); auto bal = rpc->getAllBalances()->value(nextStep->intTAddr);
auto sendAmt = bal - Utils::getMinerFee(); auto sendAmt = bal - Utils::getMinerFee();
@ -262,6 +273,7 @@ void Turnstile::executeMigrationStep() {
} }
QList<ToFields> to = { ToFields{ nextStep->destAddr, sendAmt, "", "" } }; QList<ToFields> to = { ToFields{ nextStep->destAddr, sendAmt, "", "" } };
// Create the Tx // Create the Tx
auto tx = Tx{ nextStep->intTAddr, to, Utils::getMinerFee() }; auto tx = Tx{ nextStep->intTAddr, to, Utils::getMinerFee() };

1
src/turnstile.h

@ -12,7 +12,6 @@ struct TurnstileMigrationItem {
QString destAddr; QString destAddr;
int blockNumber; int blockNumber;
double amount; double amount;
bool chaff;
int status; int status;
}; };

Loading…
Cancel
Save