Browse Source

invoice: Check duplicate preimage when explicitly sprcified.

Reported-by: @mcudev
ppa-0.6.1
ZmnSCPxj 7 years ago
committed by Rusty Russell
parent
commit
079778e357
  1. 10
      lightningd/invoice.c
  2. 6
      tests/test_lightningd.py
  3. 21
      wallet/invoices.c
  4. 15
      wallet/invoices.h
  5. 5
      wallet/test/run-wallet.c
  6. 6
      wallet/wallet.c
  7. 14
      wallet/wallet.h

10
lightningd/invoice.c

@ -297,6 +297,16 @@ static void json_invoice(struct command *cmd,
/* Generate preimage hash. */ /* Generate preimage hash. */
sha256(&rhash, r.r, sizeof(r.r)); sha256(&rhash, r.r, sizeof(r.r));
/* Check duplicate preimage if explicitly specified.
* We do not check when it is randomly generated, since
* the probability of that matching is very low.
*/
if (preimagetok &&
wallet_invoice_find_by_rhash(cmd->ld->wallet, &invoice, &rhash)) {
command_fail(cmd, "preimage already used");
return;
}
/* Construct bolt11 string. */ /* Construct bolt11 string. */
b11 = new_bolt11(cmd, msatoshi_val); b11 = new_bolt11(cmd, msatoshi_val);
b11->chain = get_chainparams(cmd->ld); b11->chain = get_chainparams(cmd->ld);

6
tests/test_lightningd.py

@ -462,6 +462,12 @@ class LightningDTests(BaseLightningDTests):
payment_preimage = payment['payment_preimage'] payment_preimage = payment['payment_preimage']
assert invoice_preimage == payment_preimage assert invoice_preimage == payment_preimage
# Creating a new invoice with same preimage should error.
self.assertRaisesRegex(ValueError,
"preimage already used",
l2.rpc.invoice, 123456, 'inv2', '?',
None, None, invoice_preimage)
def test_invoice(self): def test_invoice(self):
l1 = self.node_factory.get_node() l1 = self.node_factory.get_node()
l2 = self.node_factory.get_node() l2 = self.node_factory.get_node()

21
wallet/invoices.c

@ -347,6 +347,27 @@ bool invoices_find_by_label(struct invoices *invoices,
} }
} }
bool invoices_find_by_rhash(struct invoices *invoices,
struct invoice *pinvoice,
const struct sha256 *rhash)
{
sqlite3_stmt *stmt;
stmt = db_prepare(invoices->db,
"SELECT id"
" FROM invoices"
" WHERE payment_hash = ?;");
sqlite3_bind_blob(stmt, 1, rhash, sizeof(*rhash), SQLITE_TRANSIENT);
if (sqlite3_step(stmt) == SQLITE_ROW) {
pinvoice->id = sqlite3_column_int64(stmt, 0);
sqlite3_finalize(stmt);
return true;
} else {
sqlite3_finalize(stmt);
return false;
}
}
bool invoices_find_unpaid(struct invoices *invoices, bool invoices_find_unpaid(struct invoices *invoices,
struct invoice *pinvoice, struct invoice *pinvoice,
const struct sha256 *rhash) const struct sha256 *rhash)

15
wallet/invoices.h

@ -76,6 +76,21 @@ bool invoices_find_by_label(struct invoices *invoices,
struct invoice *pinvoice, struct invoice *pinvoice,
const struct json_escaped *label); const struct json_escaped *label);
/**
* invoices_find_by_rhash - Search for an invoice by
* payment_hash
*
* @invoices - the invoice handler.
* @pinvoice - pointer to location to load found invoice in.
* @rhash - the payment_hash to search for.
*
* Returns false if no invoice with that rhash exists.
* Returns true if found.
*/
bool invoices_find_by_rhash(struct invoices *invoices,
struct invoice *pinvoice,
const struct sha256 *rhash);
/** /**
* invoices_find_unpaid - Search for an unpaid, unexpired invoice by * invoices_find_unpaid - Search for an unpaid, unexpired invoice by
* payment_hash * payment_hash

5
wallet/test/run-wallet.c

@ -136,6 +136,11 @@ bool invoices_find_by_label(struct invoices *invoices UNNEEDED,
struct invoice *pinvoice UNNEEDED, struct invoice *pinvoice UNNEEDED,
const struct json_escaped *label UNNEEDED) const struct json_escaped *label UNNEEDED)
{ fprintf(stderr, "invoices_find_by_label called!\n"); abort(); } { fprintf(stderr, "invoices_find_by_label called!\n"); abort(); }
/* Generated stub for invoices_find_by_rhash */
bool invoices_find_by_rhash(struct invoices *invoices UNNEEDED,
struct invoice *pinvoice UNNEEDED,
const struct sha256 *rhash UNNEEDED)
{ fprintf(stderr, "invoices_find_by_rhash called!\n"); abort(); }
/* Generated stub for invoices_find_unpaid */ /* Generated stub for invoices_find_unpaid */
bool invoices_find_unpaid(struct invoices *invoices UNNEEDED, bool invoices_find_unpaid(struct invoices *invoices UNNEEDED,
struct invoice *pinvoice UNNEEDED, struct invoice *pinvoice UNNEEDED,

6
wallet/wallet.c

@ -1386,6 +1386,12 @@ bool wallet_invoice_find_by_label(struct wallet *wallet,
{ {
return invoices_find_by_label(wallet->invoices, pinvoice, label); return invoices_find_by_label(wallet->invoices, pinvoice, label);
} }
bool wallet_invoice_find_by_rhash(struct wallet *wallet,
struct invoice *pinvoice,
const struct sha256 *rhash)
{
return invoices_find_by_rhash(wallet->invoices, pinvoice, rhash);
}
bool wallet_invoice_find_unpaid(struct wallet *wallet, bool wallet_invoice_find_unpaid(struct wallet *wallet,
struct invoice *pinvoice, struct invoice *pinvoice,
const struct sha256 *rhash) const struct sha256 *rhash)

14
wallet/wallet.h

@ -510,6 +510,20 @@ bool wallet_invoice_find_by_label(struct wallet *wallet,
struct invoice *pinvoice, struct invoice *pinvoice,
const struct json_escaped *label); const struct json_escaped *label);
/**
* wallet_invoice_find_by_rhash - Search for an invoice by payment_hash
*
* @wallet - the wallet to search.
* @pinvoice - pointer to location to load found invoice in.
* @rhash - the payment_hash to search for.
*
* Returns false if no invoice with that rhash exists.
* Returns true if found.
*/
bool wallet_invoice_find_by_rhash(struct wallet *wallet,
struct invoice *pinvoice,
const struct sha256 *rhash);
/** /**
* wallet_invoice_find_unpaid - Search for an unpaid, unexpired invoice by * wallet_invoice_find_unpaid - Search for an unpaid, unexpired invoice by
* payment_hash * payment_hash

Loading…
Cancel
Save