Skip to content

Commit

Permalink
invoice: Check duplicate preimage when explicitly sprcified.
Browse files Browse the repository at this point in the history
Reported-by: @mcudev
  • Loading branch information
ZmnSCPxj authored and rustyrussell committed Apr 26, 2018
1 parent 89ff46f commit 079778e
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 0 deletions.
10 changes: 10 additions & 0 deletions lightningd/invoice.c
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,16 @@ static void json_invoice(struct command *cmd,
/* Generate preimage hash. */
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. */
b11 = new_bolt11(cmd, msatoshi_val);
b11->chain = get_chainparams(cmd->ld);
Expand Down
6 changes: 6 additions & 0 deletions tests/test_lightningd.py
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,12 @@ def test_invoice_preimage(self):
payment_preimage = payment['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):
l1 = self.node_factory.get_node()
l2 = self.node_factory.get_node()
Expand Down
21 changes: 21 additions & 0 deletions wallet/invoices.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
struct invoice *pinvoice,
const struct sha256 *rhash)
Expand Down
15 changes: 15 additions & 0 deletions wallet/invoices.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,21 @@ bool invoices_find_by_label(struct invoices *invoices,
struct invoice *pinvoice,
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
* payment_hash
Expand Down
5 changes: 5 additions & 0 deletions wallet/test/run-wallet.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,11 @@ bool invoices_find_by_label(struct invoices *invoices UNNEEDED,
struct invoice *pinvoice UNNEEDED,
const struct json_escaped *label UNNEEDED)
{ 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 */
bool invoices_find_unpaid(struct invoices *invoices UNNEEDED,
struct invoice *pinvoice UNNEEDED,
Expand Down
6 changes: 6 additions & 0 deletions wallet/wallet.c
Original file line number Diff line number Diff line change
Expand Up @@ -1386,6 +1386,12 @@ bool wallet_invoice_find_by_label(struct wallet *wallet,
{
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,
struct invoice *pinvoice,
const struct sha256 *rhash)
Expand Down
14 changes: 14 additions & 0 deletions wallet/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,20 @@ bool wallet_invoice_find_by_label(struct wallet *wallet,
struct invoice *pinvoice,
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
* payment_hash
Expand Down

0 comments on commit 079778e

Please sign in to comment.