Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow for aborting rescans in the GUI #11200

Merged
merged 2 commits into from Apr 13, 2018

Conversation

@achow101
Copy link
Member

achow101 commented Aug 31, 2017

A cancel button is added to the showProgress dialog that is used only for rescans. When clicked, AbortRescan is called directly to cancel the rescan.

Rescans triggered from the debug console will now be cancelable by clicking the cancel button.

Rescans triggered by a command (e.g. importmulti) will now give an error indicating that the rescan was aborted by the user (either by the abortrescan command or by clicking cancel).

@achow101 achow101 force-pushed the achow101:gui-recan-abort branch 2 times, most recently Aug 31, 2017

@MeshCollider
Copy link
Member

MeshCollider left a comment

utACK modulo Travis issues

src/qt/bitcoingui.cpp Outdated
progressDialog->setAutoClose(false);
progressDialog->setValue(0);

if (cancel) {
progressDialog->setCancelButtonText("Cancel");

This comment has been minimized.

@MeshCollider

MeshCollider Aug 31, 2017

Member

Does this "Cancel" need a translation?

This comment has been minimized.

@achow101

achow101 Aug 31, 2017

Author Member

Yes, it does. Done

@promag
Copy link
Member

promag left a comment

Should it be possible to abort rescans caused by the RPC calls?

I'm not very fond of callbacks. Have you thought in alternatives?

src/qt/bitcoingui.cpp Outdated
else if (progressDialog) {
if (progressDialog->wasCanceled()) {
cancel();
}

This comment has been minimized.

@promag

promag Aug 31, 2017

Member

} else {

This comment has been minimized.

@achow101

achow101 Aug 31, 2017

Author Member

Done

src/qt/bitcoingui.cpp Outdated
@@ -1119,16 +1120,21 @@ void BitcoinGUI::detectShutdown()
}
}

void BitcoinGUI::showProgress(const QString &title, int nProgress)
void BitcoinGUI::showProgress(const QString &title, int nProgress, const std::function<void(void)> &cancel)

This comment has been minimized.

@promag

promag Aug 31, 2017

Member

& are next to the type. Same for remaining changes.

This comment has been minimized.

@achow101

achow101 Aug 31, 2017

Author Member

Done

@achow101

This comment has been minimized.

Copy link
Member Author

achow101 commented Aug 31, 2017

I don't know what is causing the travis failures.

Should it be possible to abort rescans caused by the RPC calls?

Yes. There is an abortrescan RPC call that lets you abort a rescan. But it is not accessible from the GUI.

@ryanofsky
Copy link
Contributor

ryanofsky left a comment

utACK e6e8b0c259594b09e405fc9123d1f8473e42b0e4 with RPC bugfixes

src/qt/bitcoingui.cpp Outdated
@@ -487,7 +487,7 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel)
connect(_clientModel, SIGNAL(message(QString,QString,unsigned int)), this, SLOT(message(QString,QString,unsigned int)));

// Show progress dialog
connect(_clientModel, SIGNAL(showProgress(QString,int)), this, SLOT(showProgress(QString,int)));
connect(_clientModel, SIGNAL(showProgress(QString,int, std::function<void(void)>)), this, SLOT(showProgress(QString,int, std::function<void(void)>)));

This comment has been minimized.

@ryanofsky

ryanofsky Aug 31, 2017

Contributor

In commit "Add cancel function reference to ShowProgress"

A typedef or using declaration for std::function<void(void)> might make the changes throughout this commit be more readable, and also make this code less fragile because SIGNAL and SLOT macros rely on string comparison.

src/txdb.cpp Outdated
@@ -386,7 +386,7 @@ bool CCoinsViewDB::Upgrade() {
if (count++ % 256 == 0) {
uint32_t high = 0x100 * *key.second.begin() + *(key.second.begin() + 1);
int percentageDone = (int)(high * 100.0 / 65536.0 + 0.5);
uiInterface.ShowProgress(_("Upgrading UTXO database") + "\n"+ _("(press q to shutdown and continue later)") + "\n", percentageDone);
uiInterface.ShowProgress(_("Upgrading UTXO database") + "\n"+ _("(press q to shutdown and continue later)") + "\n", percentageDone, std::function<void(void)>());

This comment has been minimized.

@ryanofsky

ryanofsky Aug 31, 2017

Contributor

In commit "Add cancel function reference to ShowProgress"

No need to write std::function<void(void)>() here and 12 other places. You can just pass {} or nullptr.

This comment has been minimized.

@achow101

achow101 Aug 31, 2017

Author Member

Oh, I didn't realize that that would work. Done.

src/qt/bitcoingui.cpp Outdated
progressDialog->setValue(nProgress);
else if (progressDialog) {
if (progressDialog->wasCanceled()) {
cancel();

This comment has been minimized.

@ryanofsky

ryanofsky Aug 31, 2017

Contributor

In commit "Add cancel button to rescan progress dialog"

Maybe assert(cancel)

src/wallet/rpcdump.cpp Outdated
@@ -535,7 +556,14 @@ UniValue importwallet(const JSONRPCRequest& request)
file.close();
pwallet->ShowProgress("", 100, std::function<void(void)>()); // hide progress dialog in GUI
pwallet->UpdateTimeFirstKey(nTimeBegin);
pwallet->RescanFromTime(nTimeBegin, false /* update */);
int64_t scanned_time = pwallet->RescanFromTime(nTimeBegin, false /* update */);
if (scanned_time > TIMESTAMP_MIN) {

This comment has been minimized.

@ryanofsky

ryanofsky Aug 31, 2017

Contributor

In commit "Give an error when rescan is aborted by the user"

s/TIMESTAMP_MIN/nTimeBegin/ here to fix test failures

This comment has been minimized.

@achow101

achow101 Aug 31, 2017

Author Member

Done

@achow101 achow101 force-pushed the achow101:gui-recan-abort branch 2 times, most recently Aug 31, 2017

@ryanofsky
Copy link
Contributor

ryanofsky left a comment

utACK c8720f0a320eff0cc83a459dc87f28087d518825. Only changes were implementing various suggestions.

I'm not very fond of callbacks. Have you thought in alternatives?

Reason callback seems to be used is to avoid the need for qt code to call CWallet's AbortRescan method or set the fAbortRescan flag directly. The alternatives would be for Qt to call a different function or set a different flag, but don't seem like they would be much better or worse.

@jonasschnelli
Copy link
Member

jonasschnelli left a comment

Concept ACK

src/wallet/wallet.cpp Outdated
@@ -1568,13 +1568,13 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool f
fAbortRescan = false;
fScanningWallet = true;

ShowProgress(_("Rescanning..."), 0); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup
ShowProgress(_("Rescanning..."), 0, boost::bind(&CWallet::AbortRescan, this)); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup

This comment has been minimized.

@jonasschnelli

jonasschnelli Sep 3, 2017

Member

nit: use std::bind (and below)

This comment has been minimized.

@achow101

achow101 Sep 5, 2017

Author Member

Done

src/ui_interface.h Outdated
@@ -95,7 +95,7 @@ class CClientUIInterface
boost::signals2::signal<void (CWallet* wallet)> LoadWallet;

/** Show progress e.g. for verifychain */
boost::signals2::signal<void (const std::string &title, int nProgress)> ShowProgress;
boost::signals2::signal<void (const std::string &title, int nProgress, const std::function<void(void)>& cancel)> ShowProgress;

This comment has been minimized.

@jonasschnelli

jonasschnelli Sep 3, 2017

Member

use nullptr as default parameter for cancel to avoid adding nullptr to all non-callback ShowProgress calls?

This comment has been minimized.

@achow101

achow101 Sep 5, 2017

Author Member

I couldn't set a default parameter in the signal, so I'm not sure it is possible to do that. Or I'm just doing something wrong.

@achow101 achow101 force-pushed the achow101:gui-recan-abort branch Sep 5, 2017

@laanwj laanwj added the GUI label Sep 6, 2017

@jonasschnelli

This comment has been minimized.

Copy link
Member

jonasschnelli commented Sep 6, 2017

Tested a bit and there is a concurrency issue (maybe not related to this code but since you finally can test multiple rescans during the same runtime this PR may reveal the issue):

Sometimes the progress window does not show up (happened to me only if I canceled a rescan before) and the GUI is fully in locked state (due to the rescan).
In that case, the rescan is happening and the GUI is locked (without showing a progress screen) via cs_main in transactiontablemodel.cpp

@jonasschnelli

This comment has been minimized.

Copy link
Member

jonasschnelli commented Sep 7, 2017

Needs rebase

@ryanofsky
Copy link
Contributor

ryanofsky left a comment

utACK 4657e40f1516d506095f969dc726da6f97d57a99. Only change since last review is rebase and some whitespace diffs.

src/qt/bitcoingui.cpp Outdated
@@ -487,7 +487,7 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel)
connect(_clientModel, SIGNAL(message(QString,QString,unsigned int)), this, SLOT(message(QString,QString,unsigned int)));

// Show progress dialog
connect(_clientModel, SIGNAL(showProgress(QString,int)), this, SLOT(showProgress(QString,int)));
connect(_clientModel, SIGNAL(showProgress(QString,int, bool, std::function<void(void)>)), this, SLOT(showProgress(QString,int, std::function<void(void)>)));

This comment has been minimized.

@ryanofsky

ryanofsky Oct 12, 2017

Contributor

Could just write void() instead of void(void) everywhere

This comment has been minimized.

@achow101

achow101 Oct 31, 2017

Author Member

Done

src/qt/splashscreen.cpp Outdated
@@ -181,7 +181,7 @@ static void ShowProgress(SplashScreen *splash, const std::string &title, int nPr
#ifdef ENABLE_WALLET
void SplashScreen::ConnectWallet(CWallet* wallet)
{
wallet->ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2, false));
wallet->ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2, false, _4));

This comment has been minimized.

@ryanofsky

ryanofsky Oct 12, 2017

Contributor

You added both resume_possible and cancel arguments to the ShowProgress signal in wallet.h so this should be _3, _4, instead of false, _4.

(Another alternative if you want to ensure wallet resume_possible value is always false, is to not add resume_possible in wallet.h, and then change this to false, _3. But adding the argument and then silently ignoring like this does now isn't good.)

This comment has been minimized.

@achow101

achow101 Oct 31, 2017

Author Member

Done

This comment has been minimized.

@achow101

achow101 Oct 31, 2017

Author Member

Actually changing this seems to be causing a segfault, so I will leave it as is.

This comment has been minimized.

@MarcoFalke

MarcoFalke Mar 18, 2018

Member

The following diff appears to be working for me. Could you help me find the steps to reproduce the segfault? Otherwise, I think this is a sensible suggestion.

--- a/src/qt/splashscreen.cpp
+++ b/src/qt/splashscreen.cpp
@@ -181,7 +181,7 @@ static void ShowProgress(SplashScreen *splash, const std::string &title, int nPr
 #ifdef ENABLE_WALLET
 void SplashScreen::ConnectWallet(CWallet* wallet)
 {
-    wallet->ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2, false, _4));
+    wallet->ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2, _3, _4));
     connectedWallets.push_back(wallet);
 }
 #endif
@@ -203,7 +203,7 @@ void SplashScreen::unsubscribeFromCoreSignals()
     uiInterface.ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2, _3, _4));
 #ifdef ENABLE_WALLET
     for (CWallet* const & pwallet : connectedWallets) {
-        pwallet->ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2, false, _4));
+        pwallet->ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2, _3, _4));
     }
 #endif
 }

This comment has been minimized.

@achow101

achow101 Mar 18, 2018

Author Member

Hmm, that diff works for me. I don't remember what I did that caused a segfault. Added this change.

@promag

This comment has been minimized.

Copy link
Member

promag commented Oct 29, 2017

utACK 4657e40. Have you thought adding tests for the new RPC errors? (might be impossible?)

@jonasschnelli

This comment has been minimized.

Copy link
Member

jonasschnelli commented Oct 29, 2017

Reminder: this PR currently causes a deadlock (at least on OSX):
IMO it would require #11281 to work flawless.

@ryanofsky

This comment has been minimized.

Copy link
Contributor

ryanofsky commented Oct 31, 2017

@jonasschnelli, I don't see how this could be causing any deadlock that wasn't occurring before. The cancel callback isn't acquiring any locks, just updating an atomic<bool>. Are you sure there is a problem in the current version of this PR?

@achow101

This comment has been minimized.

Copy link
Member Author

achow101 commented Oct 31, 2017

@ryanofsky I think it is more that a deadlock currently exists in the rescanning code which this PR makes more obvious and easier to hit.

@achow101 achow101 force-pushed the achow101:gui-recan-abort branch 2 times, most recently Oct 31, 2017

@ryanofsky

This comment has been minimized.

Copy link
Contributor

ryanofsky commented Oct 31, 2017

@ryanofsky I think it is more that a deadlock currently exists in the rescanning code which this PR makes more obvious and easier to hit.

I know that's the claim, but I don't understand what the deadlock is. What does the rescan code have to do with transactiontablemodel and why would shorter aborted scans cause more UI problems than longer full scans?

@achow101 achow101 force-pushed the achow101:gui-recan-abort branch 2 times, most recently Oct 31, 2017

@ryanofsky
Copy link
Contributor

ryanofsky left a comment

utACK 449dd52b417d2a49b4de4440b391f6ebccb093b4. Same as before, just gets rid of spurious whitespace changes and void(void)

@achow101

This comment has been minimized.

Copy link
Member Author

achow101 commented Mar 31, 2018

I changed the implementation to completely remove the callback. The showProgress dialog that is used for rescans just calls AbortRescan directly when cancel is clicked. This should work since the dialog is used only for rescanning.

OP and title also updated.

The original branch with callbacks can be found here: https://github.com/achow101/bitcoin/tree/gui-rescan-abort-w-callback

@achow101 achow101 changed the title Allow for aborting rescans and canceling showProgress dialogs Allow for aborting rescans in the GUI Mar 31, 2018

@achow101 achow101 force-pushed the achow101:gui-recan-abort branch 3 times, most recently Mar 31, 2018

@achow101

This comment has been minimized.

Copy link
Member Author

achow101 commented Apr 5, 2018

Rebased

@MarcoFalke

This comment has been minimized.

Copy link
Member

MarcoFalke commented Apr 8, 2018

Needs trivial rebase to accommodate a file rename.

@achow101 achow101 force-pushed the achow101:gui-recan-abort branch Apr 8, 2018

@achow101

This comment has been minimized.

Copy link
Member Author

achow101 commented Apr 8, 2018

Rebased

@promag
Copy link
Member

promag left a comment

Some comments, will test later.

@@ -172,7 +172,13 @@ UniValue importprivkey(const JSONRPCRequest& request)
}
}
if (fRescan) {
pwallet->RescanFromTime(TIMESTAMP_MIN, reserver, true /* update */);
int64_t scanned_time = pwallet->RescanFromTime(TIMESTAMP_MIN, reserver, true /* update */);

This comment has been minimized.

@promag

promag Apr 8, 2018

Member

This code is repeated 4 times, maybe it's worth moving it to a function?

This comment has been minimized.

@ryanofsky

ryanofsky Apr 9, 2018

Contributor

In commit "Give an error when rescan is aborted by the user"

This code is repeated 4 times, maybe it's worth moving it to a function?

Could be nice, though to be honest a lot of other code is duplicated between the import* RPCs too. So effort might be better spent deduping larger chunks or deprecating older RPCs in favor of importmulti.

This comment has been minimized.

@achow101

achow101 Apr 9, 2018

Author Member

I think that should be part of a separate refactor for deduplicating all of the import* RPCs.

This comment has been minimized.

@promag

promag Apr 14, 2018

Member

Sure.

src/interfaces/wallet.h Outdated
@@ -247,6 +247,9 @@ class Wallet
//! Register handler for watchonly changed messages.
using WatchOnlyChangedFn = std::function<void(bool have_watch_only)>;
virtual std::unique_ptr<Handler> handleWatchOnlyChanged(WatchOnlyChangedFn fn) = 0;

//! Abort a rescan

This comment has been minimized.

@promag

promag Apr 8, 2018

Member

Nit, period.

This comment has been minimized.

@ryanofsky

ryanofsky Apr 9, 2018

Contributor

Would suggest renaming this method abortRescan and moving it above backupWallet (both here and in wallet.cpp). These interfaces are organized with regular methods on top and callback methods below. Also roughly with whole-wallet operations above operations on individual addresses and transactions.

This comment has been minimized.

@achow101

achow101 Apr 9, 2018

Author Member

Done (moved and added period).

src/qt/walletmodel.cpp Outdated

void WalletModel::AbortRescan() const
{
wallet().AbortRescan();

This comment has been minimized.

@promag

promag Apr 8, 2018

Member

Nit, m_wallet->AbortRescan()?

This comment has been minimized.

@ryanofsky

ryanofsky Apr 9, 2018

Contributor

In commit "Add cancel button to rescan progress dialog"

Would suggest dropping this method and just calling model.wallet().abortRescan() directly. I don't think there's a benefit to wrapping individual Wallet calls inside WalletModel methods unless they're doing extra work like synchronization or caching.

This comment has been minimized.

@achow101

achow101 Apr 9, 2018

Author Member

Removed and called directly from walletview

src/qt/walletmodel.h Outdated
@@ -204,6 +204,8 @@ class WalletModel : public QObject
QString getWalletName() const;

bool isMultiwallet();

void AbortRescan() const;

This comment has been minimized.

@promag

promag Apr 8, 2018

Member

Nit, void abortRescan() const.

This comment has been minimized.

@achow101

achow101 Apr 9, 2018

Author Member

Removed

@promag

This comment has been minimized.

Copy link
Member

promag commented Apr 8, 2018

Changing the progress dialog to be aware of the differences between init and rescan would be another way to approach this, and probably a good idea, but just a larger change.

I agree with @ryanofsky here. I'll try to push #11826 forward. Not that this shouldn't go forward.

@jonasschnelli

This comment has been minimized.

Copy link
Member

jonasschnelli commented Apr 9, 2018

Could finally test this.
I think it is an important feature because the way how users currently abort rescan is by force quitting the application (which is really not what we want).

Tested ACK bc2003cdf7102e03710dbc19e9c397b92e124fb4.
I'd like to see @promag's nits addresses (lowercase methodname in QT, interface call via class member).

@ryanofsky
Copy link
Contributor

ryanofsky left a comment

utACK bc2003cdf7102e03710dbc19e9c397b92e124fb4. This PR has changed quite a lot since it was opened but is very simple at this point and provides useful functionality.

src/interfaces/wallet.h Outdated
@@ -247,6 +247,9 @@ class Wallet
//! Register handler for watchonly changed messages.
using WatchOnlyChangedFn = std::function<void(bool have_watch_only)>;
virtual std::unique_ptr<Handler> handleWatchOnlyChanged(WatchOnlyChangedFn fn) = 0;

//! Abort a rescan

This comment has been minimized.

@ryanofsky

ryanofsky Apr 9, 2018

Contributor

Would suggest renaming this method abortRescan and moving it above backupWallet (both here and in wallet.cpp). These interfaces are organized with regular methods on top and callback methods below. Also roughly with whole-wallet operations above operations on individual addresses and transactions.

src/qt/walletmodel.cpp Outdated

void WalletModel::AbortRescan() const
{
wallet().AbortRescan();

This comment has been minimized.

@ryanofsky

ryanofsky Apr 9, 2018

Contributor

In commit "Add cancel button to rescan progress dialog"

Would suggest dropping this method and just calling model.wallet().abortRescan() directly. I don't think there's a benefit to wrapping individual Wallet calls inside WalletModel methods unless they're doing extra work like synchronization or caching.

@@ -172,7 +172,13 @@ UniValue importprivkey(const JSONRPCRequest& request)
}
}
if (fRescan) {
pwallet->RescanFromTime(TIMESTAMP_MIN, reserver, true /* update */);
int64_t scanned_time = pwallet->RescanFromTime(TIMESTAMP_MIN, reserver, true /* update */);

This comment has been minimized.

@ryanofsky

ryanofsky Apr 9, 2018

Contributor

In commit "Give an error when rescan is aborted by the user"

This code is repeated 4 times, maybe it's worth moving it to a function?

Could be nice, though to be honest a lot of other code is duplicated between the import* RPCs too. So effort might be better spent deduping larger chunks or deprecating older RPCs in favor of importmulti.

@achow101 achow101 force-pushed the achow101:gui-recan-abort branch Apr 9, 2018

@ryanofsky
Copy link
Contributor

ryanofsky left a comment

utACK 66ee39f227b28a32c6c1cb6cd68c0eee0cc8637f

src/wallet/rpcdump.cpp Outdated
@@ -534,9 +534,9 @@ UniValue importwallet(const JSONRPCRequest& request)
int64_t nFilesize = std::max((int64_t)1, (int64_t)file.tellg());
file.seekg(0, file.beg);

pwallet->ShowProgress(_("Importing..."), 0); // show progress dialog in GUI
uiInterface.ShowProgress(_("Importing..."), 0, false); // show progress dialog in GUI

This comment has been minimized.

@ryanofsky

ryanofsky Apr 9, 2018

Contributor

In commit "Add cancel button to rescan progress dialog"

These changes from wallet to global ShowProgress calls seem unrelated. Are they intentional? It might make sense to change these if removing the wallet ShowProgress signal, but since that is still used in CWallet::ScanForWalletTransactions, this change just makes these calls inconsistent.

If this change is necessary it would be good to have a comment saying why CWallet::ShowProgress is not used here.

This comment has been minimized.

@achow101

achow101 Apr 9, 2018

Author Member

Because CWallet::ShowProgress has a cancel button now which is directly tied to AbortRescan (because it isn't used for anything except showing rescan progress), I needed a different progress bar which does not have a cancel button. This change makes that ShowProgress use BitcoinGUI::ShowProgress (which is tied toe uiInterface)which does not have a cancel button (and is also not used anywhere else AFAICT). This progress bar indicates the import progress, not rescan progress which is why a different ShowProgress is needed

I added a comment.

@ryanofsky
Copy link
Contributor

ryanofsky left a comment

utACK deaffd812e3cdaeb7ec978c2d86f4bf688add96f, thanks for the comment!

achow101 added some commits Mar 31, 2018

Add cancel button to rescan progress dialog
Adds a cancel button to the rescan progress dialog. When it is clicked,
AbortRescan is called to abort a rescan

@achow101 achow101 force-pushed the achow101:gui-recan-abort branch to ae1d2b0 Apr 12, 2018

@achow101

This comment has been minimized.

Copy link
Member Author

achow101 commented Apr 12, 2018

Squashed the squashme. Is this ready for merging?

@MarcoFalke

This comment has been minimized.

Copy link
Member

MarcoFalke commented Apr 12, 2018

utACK ae1d2b0. Going to test this later...

@jonasschnelli jonasschnelli merged commit ae1d2b0 into bitcoin:master Apr 13, 2018

1 check passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details

jonasschnelli added a commit that referenced this pull request Apr 13, 2018

Merge #11200: Allow for aborting rescans in the GUI
ae1d2b0 Give an error when rescan is aborted by the user (Andrew Chow)
69b01e6 Add cancel button to rescan progress dialog (Andrew Chow)

Pull request description:

  A cancel button is added to the `showProgress` dialog that is used only for rescans. When clicked, `AbortRescan` is called directly to cancel the rescan.

  Rescans triggered from the debug console will now be cancelable by clicking the cancel button.

  Rescans triggered by a command (e.g. `importmulti`) will now give an error indicating that the rescan was aborted by the user (either by the `abortrescan` command or by clicking cancel).

Tree-SHA512: 4bb14998766de686e2318fbc9805758eccf5dbe628a7257d072c9ae2fb4f61303a0876f49988d6e5eddb261969b8a307c81c0c2df0a42ae909a43d738af3dc1b

@MarcoFalke MarcoFalke modified the milestones: 0.17.0, 0.16.1 Apr 21, 2018

@MarcoFalke MarcoFalke removed this from the 0.16.1 milestone Apr 21, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.