diff --git a/tests/test_lightningd.py b/tests/test_lightningd.py index 4b99e3bc4..6a76e1740 100644 --- a/tests/test_lightningd.py +++ b/tests/test_lightningd.py @@ -2141,6 +2141,21 @@ class LightningDTests(BaseLightningDTests): # Non-zero padding in 8-to-5 conversion self.assertRaises(ValueError, l1.rpc.withdraw, 'tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3pjxtptv', 2*amount) + # Should have 6 outputs available. + c = db.cursor() + c.execute('SELECT COUNT(*) FROM outputs WHERE status=0') + assert(c.fetchone()[0] == 6) + + out = l1.rpc.withdraw(waddr, 'all') + c = db.cursor() + c.execute('SELECT COUNT(*) FROM outputs WHERE status=0') + assert(c.fetchone()[0] == 0) + + # This should fail, can't even afford fee. + self.assertRaises(ValueError, l1.rpc.withdraw, waddr, 'all') + l1.daemon.wait_for_log('Cannot afford fee') + + def test_funding_change(self): """Add some funds, fund a channel, and make sure we remember the change """ diff --git a/wallet/walletrpc.c b/wallet/walletrpc.c index b76baaedc..accb1b937 100644 --- a/wallet/walletrpc.c +++ b/wallet/walletrpc.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -199,6 +200,7 @@ static void json_withdraw(struct command *cmd, struct pubkey changekey; secp256k1_ecdsa_signature *sigs; struct bitcoin_tx *tx; + bool withdraw_all = false; if (!json_get_params(buffer, params, "destination", &desttok, @@ -211,7 +213,9 @@ static void json_withdraw(struct command *cmd, withdraw = tal(cmd, struct withdrawal); withdraw->cmd = cmd; - if (!json_tok_u64(buffer, sattok, &withdraw->amount)) { + if (json_tok_streq(buffer, sattok, "all")) + withdraw_all = true; + else if (!json_tok_u64(buffer, sattok, &withdraw->amount)) { command_fail(cmd, "Invalid satoshis"); return; } @@ -241,13 +245,28 @@ static void json_withdraw(struct command *cmd, } /* Select the coins */ - withdraw->utxos = wallet_select_coins(cmd, cmd->ld->wallet, - withdraw->amount, - feerate_per_kw, &fee_estimate, - &withdraw->changesatoshi); - if (!withdraw->utxos) { - command_fail(cmd, "Not enough funds available"); - return; + if (withdraw_all) { + withdraw->utxos = wallet_select_all(cmd, cmd->ld->wallet, + feerate_per_kw, + &withdraw->amount, + &fee_estimate); + /* FIXME Pull dust amount from the daemon config */ + if (!withdraw->utxos || withdraw->amount < 546) { + command_fail(cmd, "Cannot afford fee %"PRIu64, + fee_estimate); + return; + } + withdraw->changesatoshi = 0; + } else { + withdraw->utxos = wallet_select_coins(cmd, cmd->ld->wallet, + withdraw->amount, + feerate_per_kw, + &fee_estimate, + &withdraw->changesatoshi); + if (!withdraw->utxos) { + command_fail(cmd, "Not enough funds available"); + return; + } } /* FIXME(cdecker) Pull this from the daemon config */ @@ -314,7 +333,7 @@ static void json_withdraw(struct command *cmd, static const struct json_command withdraw_command = { "withdraw", json_withdraw, - "Send {satoshi} to the {destination} address via Bitcoin transaction", + "Send {satoshi} (or 'all') to the {destination} address via Bitcoin transaction", "Returns the withdrawal transaction ID" }; AUTODATA(json_command, &withdraw_command);