From bac9a594b8d793cebbeb528748827bee9b5f0052 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 21 Feb 2019 14:15:55 +1030 Subject: [PATCH] wallet: use amount_sat/amount_msat. Signed-off-by: Rusty Russell --- common/wallet_tx.c | 8 +- lightningd/chaintopology.c | 10 +-- lightningd/invoice.c | 8 +- lightningd/opening_control.c | 4 +- lightningd/pay.c | 26 +++--- lightningd/peer_control.c | 2 +- lightningd/peer_htlcs.c | 41 +++++---- lightningd/test/run-invoice-select-inchan.c | 2 +- wallet/invoices.c | 14 +-- wallet/invoices.h | 4 +- wallet/test/run-wallet.c | 18 ++-- wallet/wallet.c | 99 +++++++++++++-------- wallet/wallet.h | 31 +++---- wallet/walletrpc.c | 6 +- 14 files changed, 154 insertions(+), 119 deletions(-) diff --git a/common/wallet_tx.c b/common/wallet_tx.c index 984362cc2..f73bfed4f 100644 --- a/common/wallet_tx.c +++ b/common/wallet_tx.c @@ -60,13 +60,13 @@ struct command_result *wtx_select_utxos(struct wallet_tx *tx, size_t out_len) { struct command_result *res; - u64 fee_estimate; + struct amount_sat fee_estimate; if (tx->all_funds) { struct amount_sat amount; tx->utxos = wallet_select_all(tx->cmd, tx->cmd->ld->wallet, fee_rate_per_kw, out_len, - &amount.satoshis, + &amount, &fee_estimate); res = check_amount(tx, amount); if (res) @@ -86,9 +86,9 @@ struct command_result *wtx_select_utxos(struct wallet_tx *tx, } tx->utxos = wallet_select_coins(tx->cmd, tx->cmd->ld->wallet, - tx->amount.satoshis, + tx->amount, fee_rate_per_kw, out_len, - &fee_estimate, &tx->change.satoshis); + &fee_estimate, &tx->change); res = check_amount(tx, tx->amount); if (res) return res; diff --git a/lightningd/chaintopology.c b/lightningd/chaintopology.c index 9c5f94758..a824f6948 100644 --- a/lightningd/chaintopology.c +++ b/lightningd/chaintopology.c @@ -60,7 +60,7 @@ static bool we_broadcast(const struct chain_topology *topo, static void filter_block_txs(struct chain_topology *topo, struct block *b) { size_t i; - u64 satoshi_owned; + struct amount_sat owned; /* Now we see if any of those txs are interesting. */ for (i = 0; i < tal_count(b->full_txs); i++) { @@ -83,17 +83,17 @@ static void filter_block_txs(struct chain_topology *topo, struct block *b) } } - satoshi_owned = 0; + owned = AMOUNT_SAT(0); if (txfilter_match(topo->bitcoind->ld->owned_txfilter, tx)) { wallet_extract_owned_outputs(topo->bitcoind->ld->wallet, tx, &b->height, - &satoshi_owned); + &owned); } /* We did spends first, in case that tells us to watch tx. */ bitcoin_txid(tx, &txid); if (watching_txid(topo, &txid) || we_broadcast(topo, &txid) || - satoshi_owned != 0) { + !amount_sat_eq(owned, AMOUNT_SAT(0))) { wallet_transaction_add(topo->ld->wallet, tx, b->height, i); } @@ -593,7 +593,7 @@ static void topo_add_utxos(struct chain_topology *topo, struct block *b) if (is_p2wsh(output->script, NULL)) { wallet_utxoset_add(topo->ld->wallet, tx, j, b->height, i, output->script, - output->amount); + (struct amount_sat){ output->amount }); } } } diff --git a/lightningd/invoice.c b/lightningd/invoice.c index 63f066431..1e0097580 100644 --- a/lightningd/invoice.c +++ b/lightningd/invoice.c @@ -46,15 +46,13 @@ static void json_add_invoice(struct json_stream *response, json_add_escaped_string(response, "label", inv->label); json_add_string(response, "bolt11", inv->bolt11); json_add_hex(response, "payment_hash", &inv->rhash, sizeof(inv->rhash)); - if (inv->msatoshi) - json_add_amount_msat(response, - (struct amount_msat){*inv->msatoshi}, + if (inv->msat) + json_add_amount_msat(response, *inv->msat, "msatoshi", "amount_msat"); json_add_string(response, "status", invoice_status_str(inv)); if (inv->state == PAID) { json_add_u64(response, "pay_index", inv->pay_index); - json_add_amount_msat(response, - (struct amount_msat){inv->msatoshi_received}, + json_add_amount_msat(response, inv->received, "msatoshi_received", "amount_received_msat"); json_add_u64(response, "paid_at", inv->paid_timestamp); } diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 647fe102f..8aa6ce5c2 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -291,7 +291,7 @@ static void opening_funder_finished(struct subd *openingd, const u8 *resp, struct bitcoin_tx *remote_commit; u16 funding_outnum; u32 feerate; - u64 change_satoshi; + struct amount_sat change; struct channel *channel; struct lightningd *ld = openingd->ld; @@ -426,7 +426,7 @@ static void opening_funder_finished(struct subd *openingd, const u8 *resp, tal_hex(msg, resp)); /* Extract the change output and add it to the DB */ - wallet_extract_owned_outputs(ld->wallet, fundingtx, NULL, &change_satoshi); + wallet_extract_owned_outputs(ld->wallet, fundingtx, NULL, &change); /* Make sure we recognize our change output by its scriptpubkey in * future. This assumes that we have only two outputs, may not be true diff --git a/lightningd/pay.c b/lightningd/pay.c index 4ffcdddc6..9ec9bf972 100644 --- a/lightningd/pay.c +++ b/lightningd/pay.c @@ -78,11 +78,9 @@ json_add_payment_fields(struct json_stream *response, json_add_u64(response, "id", t->id); json_add_hex(response, "payment_hash", &t->payment_hash, sizeof(t->payment_hash)); json_add_pubkey(response, "destination", &t->destination); - json_add_amount_msat(response, - ((struct amount_msat){ t->msatoshi }), + json_add_amount_msat(response, t->msatoshi, "msatoshi", "amount_msat"); - json_add_amount_msat(response, - ((struct amount_msat){ t->msatoshi_sent }), + json_add_amount_msat(response, t->msatoshi_sent, "msatoshi_sent", "amount_sent_msat"); json_add_u64(response, "created_at", t->timestamp); @@ -581,7 +579,7 @@ send_payment(struct lightningd *ld, struct command *cmd, const struct sha256 *rhash, const struct route_hop *route, - u64 msatoshi, + struct amount_msat msat, const char *description TAKES) { const u8 *onion; @@ -633,11 +631,13 @@ send_payment(struct lightningd *ld, if (payment->status == PAYMENT_COMPLETE) { log_add(ld->log, "... succeeded"); /* Must match successful payment parameters. */ - if (payment->msatoshi != msatoshi) { + if (!amount_msat_eq(payment->msatoshi, msat)) { return command_fail(cmd, PAY_RHASH_ALREADY_USED, "Already succeeded " - "with amount %"PRIu64, - payment->msatoshi); + "with amount %s", + type_to_string(tmpctx, + struct amount_msat, + &payment->msatoshi)); } if (!pubkey_eq(&payment->destination, &ids[n_hops-1])) { return command_fail(cmd, PAY_RHASH_ALREADY_USED, @@ -671,9 +671,9 @@ send_payment(struct lightningd *ld, sizeof(struct sha256), &path_secrets); onion = serialize_onionpacket(tmpctx, packet); - log_info(ld->log, "Sending %s over %zu hops to deliver %"PRIu64"", + log_info(ld->log, "Sending %s over %zu hops to deliver %s", type_to_string(tmpctx, struct amount_msat, &route[0].amount), - n_hops, msatoshi); + n_hops, type_to_string(tmpctx, struct amount_msat, &msat)); failcode = send_htlc_out(channel, route[0].amount, base_expiry + route[0].delay, @@ -709,8 +709,8 @@ send_payment(struct lightningd *ld, payment->payment_hash = *rhash; payment->destination = ids[n_hops - 1]; payment->status = PAYMENT_PENDING; - payment->msatoshi = msatoshi; - payment->msatoshi_sent = route[0].amount.millisatoshis; + payment->msatoshi = msat; + payment->msatoshi_sent = route[0].amount; payment->timestamp = time_now().ts.tv_sec; payment->payment_preimage = NULL; payment->path_secrets = tal_steal(payment, path_secrets); @@ -836,7 +836,7 @@ static struct command_result *json_sendpay(struct command *cmd, } res = send_payment(cmd->ld, cmd, rhash, route, - msat ? msat->millisatoshis : route[routetok->size-1].amount.millisatoshis, + msat ? *msat : route[routetok->size-1].amount, description); if (res) return res; diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 2ddc78843..0081bc88e 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -1324,7 +1324,7 @@ static struct command_result *json_getinfo(struct command *cmd, json_add_num(response, "blockheight", get_block_height(cmd->ld->topology)); json_add_string(response, "network", get_chainparams(cmd->ld)->network_name); json_add_amount_msat(response, - (struct amount_msat){ wallet_total_forward_fees(cmd->ld->wallet) }, + wallet_total_forward_fees(cmd->ld->wallet), "msatoshi_fees_collected", "fees_collected_msat"); json_object_end(response); return command_success(cmd, response); diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index b0d00a101..acc2e6a28 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -302,19 +302,26 @@ static void handle_localpay(struct htlc_in *hin, * - if the amount paid is less than the amount expected: * - MUST fail the HTLC. */ - if (details->msatoshi != NULL && hin->msat.millisatoshis < *details->msatoshi) { - failcode = WIRE_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS; - goto fail; - } else if (details->msatoshi != NULL && hin->msat.millisatoshis > *details->msatoshi * 2) { - /* FIXME: bolt update fixes this quote! */ - /* BOLT #4: - * - * - if the amount paid is more than twice the amount expected: - * - SHOULD fail the HTLC. - * - SHOULD return an `incorrect_payment_amount` error. - */ - failcode = WIRE_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS; - goto fail; + if (details->msat != NULL) { + struct amount_msat twice; + + if (amount_msat_less(hin->msat, *details->msat)) { + failcode = WIRE_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS; + goto fail; + } + + if (amount_msat_add(&twice, *details->msat, *details->msat) + && amount_msat_greater(hin->msat, twice)) { + /* FIXME: bolt update fixes this quote! */ + /* BOLT #4: + * + * - if the amount paid is more than twice the amount expected: + * - SHOULD fail the HTLC. + * - SHOULD return an `incorrect_payment_amount` error. + */ + failcode = WIRE_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS; + goto fail; + } } /* BOLT #4: @@ -341,7 +348,7 @@ static void handle_localpay(struct htlc_in *hin, type_to_string(tmpctx, struct amount_msat, &hin->msat), cltv_expiry); fulfill_htlc(hin, &details->r); - wallet_invoice_resolve(ld->wallet, invoice, hin->msat.millisatoshis); + wallet_invoice_resolve(ld->wallet, invoice, hin->msat); return; @@ -1886,13 +1893,13 @@ static void listforwardings_add_forwardings(struct json_stream *response, struct json_add_short_channel_id(response, "in_channel", &cur->channel_in); json_add_short_channel_id(response, "out_channel", &cur->channel_out); json_add_amount_msat(response, - (struct amount_msat) { cur->msatoshi_in }, + cur->msat_in, "in_msatoshi", "in_msat"); json_add_amount_msat(response, - (struct amount_msat) { cur->msatoshi_out }, + cur->msat_out, "out_msatoshi", "out_msat"); json_add_amount_msat(response, - (struct amount_msat) { cur->fee }, + cur->fee, "fee", "fee_msat"); json_add_string(response, "status", forward_status_name(cur->status)); json_object_end(response); diff --git a/lightningd/test/run-invoice-select-inchan.c b/lightningd/test/run-invoice-select-inchan.c index 02d16450f..519c946a7 100644 --- a/lightningd/test/run-invoice-select-inchan.c +++ b/lightningd/test/run-invoice-select-inchan.c @@ -525,7 +525,7 @@ void wallet_invoice_waitone(const tal_t *ctx UNNEEDED, void wallet_peer_delete(struct wallet *w UNNEEDED, u64 peer_dbid UNNEEDED) { fprintf(stderr, "wallet_peer_delete called!\n"); abort(); } /* Generated stub for wallet_total_forward_fees */ -u64 wallet_total_forward_fees(struct wallet *w UNNEEDED) +struct amount_msat wallet_total_forward_fees(struct wallet *w UNNEEDED) { fprintf(stderr, "wallet_total_forward_fees called!\n"); abort(); } /* Generated stub for wallet_transaction_locate */ struct txlocator *wallet_transaction_locate(const tal_t *ctx UNNEEDED, struct wallet *w UNNEEDED, diff --git a/wallet/invoices.c b/wallet/invoices.c index 2429c7c30..c318c8141 100644 --- a/wallet/invoices.c +++ b/wallet/invoices.c @@ -103,17 +103,17 @@ static struct invoice_details *wallet_stmt2invoice_details(const tal_t *ctx, dtl->label = sqlite3_column_json_escaped(dtl, stmt, 3); if (sqlite3_column_type(stmt, 4) != SQLITE_NULL) { - dtl->msatoshi = tal(dtl, u64); - *dtl->msatoshi = sqlite3_column_int64(stmt, 4); + dtl->msat = tal(dtl, struct amount_msat); + *dtl->msat = sqlite3_column_amount_msat(stmt, 4); } else { - dtl->msatoshi = NULL; + dtl->msat = NULL; } dtl->expiry_time = sqlite3_column_int64(stmt, 5); if (dtl->state == PAID) { dtl->pay_index = sqlite3_column_int64(stmt, 6); - dtl->msatoshi_received = sqlite3_column_int64(stmt, 7); + dtl->received = sqlite3_column_amount_msat(stmt, 7); dtl->paid_timestamp = sqlite3_column_int64(stmt, 8); } @@ -303,7 +303,7 @@ bool invoices_create(struct invoices *invoices, sqlite3_bind_blob(stmt, 2, r, sizeof(struct preimage), SQLITE_TRANSIENT); sqlite3_bind_int(stmt, 3, UNPAID); if (msat) - sqlite3_bind_int64(stmt, 4, msat->millisatoshis); + sqlite3_bind_amount_msat(stmt, 4, *msat); else sqlite3_bind_null(stmt, 4); sqlite3_bind_json_escaped(stmt, 5, label); @@ -508,7 +508,7 @@ static s64 get_next_pay_index(struct db *db) void invoices_resolve(struct invoices *invoices, struct invoice invoice, - u64 msatoshi_received) + struct amount_msat received) { sqlite3_stmt *stmt; s64 pay_index; @@ -528,7 +528,7 @@ void invoices_resolve(struct invoices *invoices, " WHERE id=?;"); sqlite3_bind_int(stmt, 1, PAID); sqlite3_bind_int64(stmt, 2, pay_index); - sqlite3_bind_int64(stmt, 3, msatoshi_received); + sqlite3_bind_amount_msat(stmt, 3, received); sqlite3_bind_int64(stmt, 4, paid_timestamp); sqlite3_bind_int64(stmt, 5, invoice.id); db_exec_prepared(invoices->db, stmt); diff --git a/wallet/invoices.h b/wallet/invoices.h index ab0ddee99..41a250f26 100644 --- a/wallet/invoices.h +++ b/wallet/invoices.h @@ -174,14 +174,14 @@ const struct invoice_details *invoices_iterator_deref( * * @invoices - the invoice handler. * @invoice - the invoice to mark as paid. - * @msatoshi_received - the actual amount received. + * @received - the actual amount received. * * Precondition: the invoice must not yet be expired (invoices * does not check). */ void invoices_resolve(struct invoices *invoices, struct invoice invoice, - u64 msatoshi_received); + struct amount_msat received); /** * invoices_waitany - Wait for any invoice to be paid. diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 9f63f7887..a3c51f2bc 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -174,7 +174,7 @@ struct invoices *invoices_new(const tal_t *ctx UNNEEDED, /* Generated stub for invoices_resolve */ void invoices_resolve(struct invoices *invoices UNNEEDED, struct invoice invoice UNNEEDED, - u64 msatoshi_received UNNEEDED) + struct amount_msat received UNNEEDED) { fprintf(stderr, "invoices_resolve called!\n"); abort(); } /* Generated stub for invoices_waitany */ void invoices_waitany(const tal_t *ctx UNNEEDED, @@ -683,7 +683,7 @@ static bool test_wallet_outputs(struct lightningd *ld, const tal_t *ctx) struct wallet *w = create_test_wallet(ld, ctx); struct utxo u; struct pubkey pk; - u64 fee_estimate, change_satoshis; + struct amount_sat fee_estimate, change_satoshis; const struct utxo **utxos; CHECK(w); @@ -711,7 +711,7 @@ static bool test_wallet_outputs(struct lightningd *ld, const tal_t *ctx) "wallet_add_utxo with close_info"); /* Now select them */ - utxos = wallet_select_coins(w, w, 2, 0, 21, &fee_estimate, &change_satoshis); + utxos = wallet_select_coins(w, w, AMOUNT_SAT(2), 0, 21, &fee_estimate, &change_satoshis); CHECK(utxos && tal_count(utxos) == 2); u = *utxos[1]; @@ -1106,8 +1106,8 @@ static bool test_payment_crud(struct lightningd *ld, const tal_t *ctx) memset(&t->destination, 1, sizeof(t->destination)); t->id = 0; - t->msatoshi = 100; - t->msatoshi_sent = 101; + t->msatoshi = AMOUNT_MSAT(100); + t->msatoshi_sent = AMOUNT_MSAT(101); t->status = PAYMENT_PENDING; t->payment_preimage = NULL; memset(&t->payment_hash, 1, sizeof(t->payment_hash)); @@ -1119,8 +1119,8 @@ static bool test_payment_crud(struct lightningd *ld, const tal_t *ctx) CHECK(t2 != NULL); CHECK(t2->status == t->status); CHECK(pubkey_cmp(&t2->destination, &t->destination) == 0); - CHECK(t2->msatoshi == t->msatoshi); - CHECK(t2->msatoshi_sent == t->msatoshi_sent); + CHECK(amount_msat_eq(t2->msatoshi, t->msatoshi)); + CHECK(amount_msat_eq(t2->msatoshi_sent, t->msatoshi_sent)); CHECK(!t2->payment_preimage); t->status = PAYMENT_COMPLETE; @@ -1132,8 +1132,8 @@ static bool test_payment_crud(struct lightningd *ld, const tal_t *ctx) CHECK(t2 != NULL); CHECK(t2->status == t->status); CHECK(pubkey_cmp(&t2->destination, &t->destination) == 0); - CHECK(t2->msatoshi == t->msatoshi); - CHECK(t2->msatoshi_sent == t->msatoshi_sent); + CHECK(amount_msat_eq(t2->msatoshi, t->msatoshi)); + CHECK(amount_msat_eq(t2->msatoshi_sent, t->msatoshi_sent)); CHECK(preimage_eq(t->payment_preimage, t2->payment_preimage)); db_commit_transaction(w->db); diff --git a/wallet/wallet.c b/wallet/wallet.c index 2a91abd62..e29bc6056 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -250,12 +250,12 @@ void wallet_confirm_utxos(struct wallet *w, const struct utxo **utxos) } static const struct utxo **wallet_select(const tal_t *ctx, struct wallet *w, - const u64 value, + struct amount_sat sat, const u32 feerate_per_kw, size_t outscriptlen, bool may_have_change, - u64 *satoshi_in, - u64 *fee_estimate) + struct amount_sat *satoshi_in, + struct amount_sat *fee_estimate) { size_t i = 0; struct utxo **available; @@ -273,13 +273,14 @@ static const struct utxo **wallet_select(const tal_t *ctx, struct wallet *w, if (may_have_change) weight += (8 + 1 + BITCOIN_SCRIPTPUBKEY_P2WPKH_LEN) * 4; - *fee_estimate = 0; - *satoshi_in = 0; + *fee_estimate = AMOUNT_SAT(0); + *satoshi_in = AMOUNT_SAT(0); available = wallet_get_utxos(ctx, w, output_state_available); for (i = 0; i < tal_count(available); i++) { size_t input_weight; + struct amount_sat needed; struct utxo *u = tal_steal(utxos, available[i]); tal_arr_expand(&utxos, u); @@ -304,9 +305,22 @@ static const struct utxo **wallet_select(const tal_t *ctx, struct wallet *w, weight += input_weight; - *fee_estimate = weight * feerate_per_kw / 1000; - *satoshi_in += utxos[i]->amount.satoshis; - if (*satoshi_in >= *fee_estimate + value) + if (!amount_sat_add(satoshi_in, *satoshi_in, utxos[i]->amount)) + fatal("Overflow in available satoshis %zu/%zu %s + %s", + i, tal_count(available), + type_to_string(tmpctx, struct amount_sat, + satoshi_in), + type_to_string(tmpctx, struct amount_sat, + &utxos[i]->amount)); + + *fee_estimate = amount_tx_fee(feerate_per_kw, weight); + if (!amount_sat_add(&needed, sat, *fee_estimate)) + fatal("Overflow in fee estimate %zu/%zu %s + %s", + i, tal_count(available), + type_to_string(tmpctx, struct amount_sat, &sat), + type_to_string(tmpctx, struct amount_sat, + fee_estimate)); + if (amount_sat_greater_eq(*satoshi_in, needed)) break; } tal_free(available); @@ -315,45 +329,45 @@ static const struct utxo **wallet_select(const tal_t *ctx, struct wallet *w, } const struct utxo **wallet_select_coins(const tal_t *ctx, struct wallet *w, - const u64 value, + struct amount_sat sat, const u32 feerate_per_kw, size_t outscriptlen, - u64 *fee_estimate, u64 *changesatoshi) + struct amount_sat *fee_estimate, + struct amount_sat *change) { - u64 satoshi_in; + struct amount_sat satoshi_in; const struct utxo **utxo; - utxo = wallet_select(ctx, w, value, feerate_per_kw, + utxo = wallet_select(ctx, w, sat, feerate_per_kw, outscriptlen, true, &satoshi_in, fee_estimate); /* Couldn't afford it? */ - if (satoshi_in < *fee_estimate + value) + if (!amount_sat_sub(change, satoshi_in, sat) + || !amount_sat_sub(change, *change, *fee_estimate)) return tal_free(utxo); - *changesatoshi = satoshi_in - value - *fee_estimate; return utxo; } const struct utxo **wallet_select_all(const tal_t *ctx, struct wallet *w, const u32 feerate_per_kw, size_t outscriptlen, - u64 *value, - u64 *fee_estimate) + struct amount_sat *value, + struct amount_sat *fee_estimate) { - u64 satoshi_in; + struct amount_sat satoshi_in; const struct utxo **utxo; /* Huge value, but won't overflow on addition */ - utxo = wallet_select(ctx, w, (1ULL << 56), feerate_per_kw, + utxo = wallet_select(ctx, w, AMOUNT_SAT(1ULL << 56), feerate_per_kw, outscriptlen, false, &satoshi_in, fee_estimate); /* Can't afford fees? */ - if (*fee_estimate > satoshi_in) + if (!amount_sat_sub(value, satoshi_in, *fee_estimate)) return tal_free(utxo); - *value = satoshi_in - *fee_estimate; return utxo; } @@ -1112,9 +1126,12 @@ void wallet_confirm_tx(struct wallet *w, } int wallet_extract_owned_outputs(struct wallet *w, const struct bitcoin_tx *tx, - const u32 *blockheight, u64 *total_satoshi) + const u32 *blockheight, + struct amount_sat *total) { int num_utxos = 0; + + *total = AMOUNT_SAT(0); for (size_t output = 0; output < tal_count(tx->output); output++) { struct utxo *utxo; u32 index; @@ -1155,7 +1172,12 @@ int wallet_extract_owned_outputs(struct wallet *w, const struct bitcoin_tx *tx, } outpointfilter_add(w->owned_outpoints, &utxo->txid, utxo->outnum); - *total_satoshi += utxo->amount.satoshis; + if (!amount_sat_add(total, *total, utxo->amount)) + fatal("Cannot add utxo output %zu/%zu %s + %s", + output, tal_count(tx->output), + type_to_string(tmpctx, struct amount_sat, total), + type_to_string(tmpctx, struct amount_sat, + &utxo->amount)); tal_free(utxo); num_utxos++; } @@ -1531,7 +1553,7 @@ wallet_invoice_iterator_deref(const tal_t *ctx, struct wallet *wallet, } void wallet_invoice_resolve(struct wallet *wallet, struct invoice invoice, - u64 msatoshi_received) + struct amount_msat msatoshi_received) { invoices_resolve(wallet->invoices, invoice, msatoshi_received); } @@ -1679,7 +1701,7 @@ void wallet_payment_store(struct wallet *wallet, sqlite3_bind_int(stmt, 1, payment->status); sqlite3_bind_sha256(stmt, 2, &payment->payment_hash); sqlite3_bind_pubkey(stmt, 3, &payment->destination); - sqlite3_bind_int64(stmt, 4, payment->msatoshi); + sqlite3_bind_amount_msat(stmt, 4, payment->msatoshi); sqlite3_bind_int(stmt, 5, payment->timestamp); sqlite3_bind_blob(stmt, 6, payment->path_secrets, tal_bytelen(payment->path_secrets), @@ -1687,7 +1709,7 @@ void wallet_payment_store(struct wallet *wallet, sqlite3_bind_pubkey_array(stmt, 7, payment->route_nodes); sqlite3_bind_short_channel_id_array(stmt, 8, payment->route_channels); - sqlite3_bind_int64(stmt, 9, payment->msatoshi_sent); + sqlite3_bind_amount_msat(stmt, 9, payment->msatoshi_sent); if (payment->description != NULL) sqlite3_bind_text(stmt, 10, payment->description, @@ -1730,7 +1752,7 @@ static struct wallet_payment *wallet_stmt2payment(const tal_t *ctx, payment->status = sqlite3_column_int(stmt, 1); sqlite3_column_pubkey(stmt, 2, &payment->destination); - payment->msatoshi = sqlite3_column_int64(stmt, 3); + payment->msatoshi = sqlite3_column_amount_msat(stmt, 3); sqlite3_column_sha256(stmt, 4, &payment->payment_hash); payment->timestamp = sqlite3_column_int(stmt, 5); @@ -1747,7 +1769,7 @@ static struct wallet_payment *wallet_stmt2payment(const tal_t *ctx, payment->route_channels = sqlite3_column_short_channel_id_array(payment, stmt, 9); - payment->msatoshi_sent = sqlite3_column_int64(stmt, 10); + payment->msatoshi_sent = sqlite3_column_amount_msat(stmt, 10); if (sqlite3_column_type(stmt, 11) != SQLITE_NULL) payment->description = tal_strdup( @@ -2184,7 +2206,7 @@ wallet_outpoint_spend(struct wallet *w, const tal_t *ctx, const u32 blockheight, void wallet_utxoset_add(struct wallet *w, const struct bitcoin_tx *tx, const u32 outnum, const u32 blockheight, const u32 txindex, const u8 *scriptpubkey, - const u64 satoshis) + struct amount_sat sat) { sqlite3_stmt *stmt; struct bitcoin_txid txid; @@ -2205,7 +2227,7 @@ void wallet_utxoset_add(struct wallet *w, const struct bitcoin_tx *tx, sqlite3_bind_null(stmt, 4); sqlite3_bind_int(stmt, 5, txindex); sqlite3_bind_blob(stmt, 6, scriptpubkey, tal_count(scriptpubkey), SQLITE_TRANSIENT); - sqlite3_bind_int64(stmt, 7, satoshis); + sqlite3_bind_amount_sat(stmt, 7, sat); db_exec_prepared(w->db, stmt); outpointfilter_add(w->utxoset_outpoints, &txid, outnum); @@ -2460,10 +2482,10 @@ void wallet_forwarded_payment_add(struct wallet *w, const struct htlc_in *in, db_exec_prepared(w->db, stmt); } -u64 wallet_total_forward_fees(struct wallet *w) +struct amount_msat wallet_total_forward_fees(struct wallet *w) { sqlite3_stmt *stmt; - u64 total; + struct amount_msat total; int res; stmt = db_prepare(w->db, @@ -2477,7 +2499,7 @@ u64 wallet_total_forward_fees(struct wallet *w) res = sqlite3_step(stmt); assert(res == SQLITE_ROW); - total = sqlite3_column_int64(stmt, 0); + total = sqlite3_column_amount_msat(stmt, 0); db_stmt_done(stmt); return total; @@ -2504,9 +2526,16 @@ const struct forwarding *wallet_forwarded_payments_get(struct wallet *w, tal_resize(&results, count+1); struct forwarding *cur = &results[count]; cur->status = sqlite3_column_int(stmt, 0); - cur->msatoshi_in = sqlite3_column_int64(stmt, 1); - cur->msatoshi_out = sqlite3_column_int64(stmt, 2); - cur->fee = cur->msatoshi_in - cur->msatoshi_out; + cur->msat_in = sqlite3_column_amount_msat(stmt, 1); + cur->msat_out = sqlite3_column_amount_msat(stmt, 2); + if (!amount_msat_sub(&cur->fee, cur->msat_in, cur->msat_out)) { + log_broken(w->log, "Forwarded in %s less than out %s!", + type_to_string(tmpctx, struct amount_msat, + &cur->msat_in), + type_to_string(tmpctx, struct amount_msat, + &cur->msat_out)); + cur->fee = AMOUNT_MSAT(0); + } if (sqlite3_column_type(stmt, 3) != SQLITE_NULL) { cur->payment_hash = tal(ctx, struct sha256_double); diff --git a/wallet/wallet.h b/wallet/wallet.h index b6bb0dbf7..43e24a3d8 100644 --- a/wallet/wallet.h +++ b/wallet/wallet.h @@ -162,7 +162,7 @@ static inline const char* forward_status_name(enum forward_status status) struct forwarding { struct short_channel_id channel_in, channel_out; - u64 msatoshi_in, msatoshi_out, fee; + struct amount_msat msat_in, msat_out, fee; struct sha256_double *payment_hash; enum forward_status status; }; @@ -216,8 +216,8 @@ struct wallet_payment { struct sha256 payment_hash; enum wallet_payment_status status; struct pubkey destination; - u64 msatoshi; - u64 msatoshi_sent; + struct amount_msat msatoshi; + struct amount_msat msatoshi_sent; /* If and only if PAYMENT_COMPLETE */ struct preimage *payment_preimage; /* Needed for recovering from routing failures. */ @@ -316,17 +316,17 @@ struct utxo **wallet_get_unconfirmed_closeinfo_utxos(const tal_t *ctx, struct wallet *w); const struct utxo **wallet_select_coins(const tal_t *ctx, struct wallet *w, - const u64 value, + struct amount_sat value, const u32 feerate_per_kw, size_t outscriptlen, - u64 *fee_estimate, - u64 *change_satoshi); + struct amount_sat *fee_estimate, + struct amount_sat *change_satoshi); const struct utxo **wallet_select_all(const tal_t *ctx, struct wallet *w, const u32 feerate_per_kw, size_t outscriptlen, - u64 *value, - u64 *fee_estimate); + struct amount_sat *sat, + struct amount_sat *fee_estimate); /** * wallet_confirm_utxos - Once we've spent a set of utxos, mark them confirmed. @@ -466,7 +466,8 @@ void wallet_blocks_heights(struct wallet *w, u32 def, u32 *min, u32 *max); * wallet_extract_owned_outputs - given a tx, extract all of our outputs */ int wallet_extract_owned_outputs(struct wallet *w, const struct bitcoin_tx *tx, - const u32 *blockheight, u64 *total_satoshi); + const u32 *blockheight, + struct amount_sat *total); /** * wallet_htlc_save_in - store an htlc_in in the database @@ -576,13 +577,13 @@ struct invoice_details { /* Label assigned by user */ const struct json_escaped *label; /* NULL if they specified "any" */ - u64 *msatoshi; + struct amount_msat *msat; /* Absolute UNIX epoch time this will expire */ u64 expiry_time; /* Set if state == PAID; order to be returned by waitanyinvoice */ u64 pay_index; /* Set if state == PAID; amount received */ - u64 msatoshi_received; + struct amount_msat received; /* Set if state == PAID; time paid */ u64 paid_timestamp; /* BOLT11 encoding for this invoice */ @@ -744,14 +745,14 @@ const struct invoice_details *wallet_invoice_iterator_deref(const tal_t *ctx, * * @wallet - the wallet containing the invoice. * @invoice - the invoice to mark as paid. - * @msatoshi_received - the actual amount received. + * @received - the actual amount received. * * Precondition: the invoice must not yet be expired (wallet * does not check!). */ void wallet_invoice_resolve(struct wallet *wallet, struct invoice invoice, - u64 msatoshi_received); + struct amount_msat received); /** * wallet_invoice_waitany - Wait for any invoice to be paid. @@ -975,7 +976,7 @@ struct outpoint *wallet_outpoint_for_scid(struct wallet *w, tal_t *ctx, void wallet_utxoset_add(struct wallet *w, const struct bitcoin_tx *tx, const u32 outnum, const u32 blockheight, const u32 txindex, const u8 *scriptpubkey, - const u64 satoshis); + struct amount_sat sat); void wallet_transaction_add(struct wallet *w, const struct bitcoin_tx *tx, const u32 blockheight, const u32 txindex); @@ -1029,7 +1030,7 @@ void wallet_forwarded_payment_add(struct wallet *w, const struct htlc_in *in, /** * Retrieve summary of successful forwarded payments' fees */ -u64 wallet_total_forward_fees(struct wallet *w); +struct amount_msat wallet_total_forward_fees(struct wallet *w); /** * Retrieve a list of all forwarded_payments diff --git a/wallet/walletrpc.c b/wallet/walletrpc.c index 7b9b85255..d2cb3d366 100644 --- a/wallet/walletrpc.c +++ b/wallet/walletrpc.c @@ -48,7 +48,7 @@ static void wallet_withdrawal_broadcast(struct bitcoind *bitcoind UNUSED, { struct command *cmd = withdraw->cmd; struct lightningd *ld = withdraw->cmd->ld; - u64 change_satoshi = 0; + struct amount_sat change = AMOUNT_SAT(0); /* Massage output into shape so it doesn't kill the JSON serialization */ char *output = tal_strjoin(cmd, tal_strsplit(cmd, msg, "\n", STR_NO_EMPTY), " ", STR_NO_TRAIL); @@ -62,11 +62,11 @@ static void wallet_withdrawal_broadcast(struct bitcoind *bitcoind UNUSED, assert(tx != NULL); /* Extract the change output and add it to the DB */ - wallet_extract_owned_outputs(ld->wallet, tx, NULL, &change_satoshi); + wallet_extract_owned_outputs(ld->wallet, tx, NULL, &change); /* Note normally, change_satoshi == withdraw->wtx.change, but * not if we're actually making a payment to ourselves! */ - assert(change_satoshi >= withdraw->wtx.change.satoshis); + assert(amount_sat_greater_eq(change, withdraw->wtx.change)); struct json_stream *response = json_stream_success(cmd); json_object_start(response, NULL);