From 43a9e2f1ca72ceb37feb3c571896fdd542f7ccfb Mon Sep 17 00:00:00 2001 From: positiveblue Date: Mon, 29 May 2023 10:20:43 -0700 Subject: [PATCH 01/10] multi: add sqlc support sqlc is a tool that generates fully type-safe idiomatic code from SQL. The result is Go code can then used execute the queries in the database. The noraml flow looks like: - The developer write some sql that will update the schema in the database: new tables, indices, etc - The developer updates the set of queries that will use the new schema. - `sqlc` generates type-safe interfaces to those queries. - The developer can then write application code that calls the methods generated by sqlc. The tool configuration needs to live in the repo's root and its name is `sqlc.yaml`. LND will support out of the box sqlite and postgres. The sql code needs to be (almost) the same for both engines, so we cannot use custom functions like `ANY` in postgres. The SQLC config file needs to define what is the target engine, we will set postgres but the generated code can be executed by sqlite too. In some specific cases, we will `match and replace` some sql lines to be sure the table definitions are valid for the targeted engine. --- Makefile | 8 ++++++++ scripts/gen_sqlc_docker.sh | 19 +++++++++++++++++++ sqlc.yaml | 10 ++++++++++ 3 files changed, 37 insertions(+) create mode 100755 scripts/gen_sqlc_docker.sh create mode 100644 sqlc.yaml diff --git a/Makefile b/Makefile index f5bf7289a..ec1aa7128 100644 --- a/Makefile +++ b/Makefile @@ -249,6 +249,14 @@ list: grep -v Makefile | \ sort +sqlc: + @$(call print, "Generating sql models and queries in Go") + ./scripts/gen_sqlc_docker.sh + +sqlc-check: sqlc + @$(call print, "Verifying sql code generation.") + if test -n "$$(git status --porcelain '*.go')"; then echo "SQL models not properly generated!"; git status --porcelain '*.go'; exit 1; fi + rpc: @$(call print, "Compiling protos.") cd ./lnrpc; ./gen_protos_docker.sh diff --git a/scripts/gen_sqlc_docker.sh b/scripts/gen_sqlc_docker.sh new file mode 100755 index 000000000..9c8e88487 --- /dev/null +++ b/scripts/gen_sqlc_docker.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +set -e + +# Directory of the script file, independent of where it's called from. +DIR="$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)" +# Use the user's cache directories +GOCACHE=`go env GOCACHE` +GOMODCACHE=`go env GOMODCACHE` + +echo "Generating sql models and queries in go..." + +docker run \ + --rm \ + --user "$UID:$(id -g)" \ + -e UID=$UID \ + -v "$DIR/../:/build" \ + -w /build \ + kjconroy/sqlc:1.18.0 generate diff --git a/sqlc.yaml b/sqlc.yaml new file mode 100644 index 000000000..2df372db1 --- /dev/null +++ b/sqlc.yaml @@ -0,0 +1,10 @@ +version: "2" +sql: + - engine: "postgresql" + schema: "sqldb/sqlc/migrations" + queries: "sqldb/sqlc/queries" + gen: + go: + out: sqldb/sqlc + package: sqlc + emit_interface: true From e3663b99424c217eab1526134f6ce65e10e2d59c Mon Sep 17 00:00:00 2001 From: positiveblue Date: Mon, 29 May 2023 10:54:35 -0700 Subject: [PATCH 02/10] sqldb: add invoices SQL schema This is the schema for "ordinal" BOLT11 invoices. The invoices table aims to keep an entry for each invoice, BOLT11 or not, that will be supported. Invoice related HTLCs will be stored in a separete table than forwarded htlcs. SQLite does not support `SEQUENCE`. We achieve atomic autoincrementals using primary keys with autoincrement/serial. An invoice `AddIndex` translates to `invoices(id)` while `SettleIndex` is `invoice_payments(id)`. --- .../sqlc/migrations/000001_invoices.down.sql | 19 +++ sqldb/sqlc/migrations/000001_invoices.up.sql | 154 ++++++++++++++++++ 2 files changed, 173 insertions(+) create mode 100644 sqldb/sqlc/migrations/000001_invoices.down.sql create mode 100644 sqldb/sqlc/migrations/000001_invoices.up.sql diff --git a/sqldb/sqlc/migrations/000001_invoices.down.sql b/sqldb/sqlc/migrations/000001_invoices.down.sql new file mode 100644 index 000000000..0e275b344 --- /dev/null +++ b/sqldb/sqlc/migrations/000001_invoices.down.sql @@ -0,0 +1,19 @@ +DROP INDEX IF EXISTS invoice_payments_invoice_id_idx; +DROP INDEX IF EXISTS invoice_payments_settled_at_idx; +DROP TABLE IF EXISTS invoice_payments; + +DROP INDEX IF EXISTS invoice_htlc_custom_records_htlc_id_idx; +DROP TABLE IF EXISTS invoice_htlc_custom_records; + +DROP INDEX IF EXISTS invoice_htlc_invoice_id_idx; +DROP TABLE IF EXISTS invoice_htlcs; + +DROP INDEX IF EXISTS invoice_feature_invoice_id_idx; +DROP TABLE IF EXISTS invoice_features; + +DROP INDEX IF EXISTS invoices_created_at_idx; +DROP INDEX IF EXISTS invoices_state_idx; +DROP INDEX IF EXISTS invoices_payment_addr_idx; +DROP INDEX IF EXISTS invoices_preimage_idx; +DROP INDEX IF EXISTS invoices_hash_idx; +DROP TABLE IF EXISTS invoices; diff --git a/sqldb/sqlc/migrations/000001_invoices.up.sql b/sqldb/sqlc/migrations/000001_invoices.up.sql new file mode 100644 index 000000000..32b70b9fa --- /dev/null +++ b/sqldb/sqlc/migrations/000001_invoices.up.sql @@ -0,0 +1,154 @@ +-- invoices table contains all the information shared by all the invoice types. +CREATE TABLE IF NOT EXISTS invoices ( + -- The id of the invoice. Translates to the AddIndex. + id INTEGER PRIMARY KEY, + + -- The hash for this invoice. The invoice hash will always identify that + -- invoice. + hash BLOB NOT NULL UNIQUE, + + -- The preimage for the hash in this invoice. Some invoices may have this + -- field empty, like unsettled hodl invoices or AMP invoices. + preimage BLOB, + + -- An optional memo to attach along with the invoice. + memo TEXT, + + -- The amount of the invoice in millisatoshis. + amount_msat BIGINT NOT NULL, + + -- Delta to use for the time-lock of the CLTV extended to the final hop. + -- BOLT12 invoices will have this field set to NULL. + cltv_delta INTEGER, + + -- The time before this invoice expiries, in seconds. + expiry INTEGER NOT NULL, + + -- A randomly generated value include in the MPP record by the sender to + -- prevent probing of the receiver. + -- This field corresponds to the `payment_secret` specified in BOLT 11. + payment_addr BLOB UNIQUE, + + -- The encoded payment request for this invoice. Some invoice types may + -- not have leave this empty, like Keysends. + payment_request TEXT UNIQUE, + + -- The invoice state. + state SMALLINT NOT NULL, + + -- The accumulated value of all the htlcs settled for this invoice. + amount_paid_msat BIGINT NOT NULL, + + -- This field will be true for AMP invoices. + is_amp BOOLEAN NOT NULL, + + -- This field will be true for hodl invoices, independently of they being + -- settled or not. + is_hodl BOOLEAN NOT NULL, + + -- This field will be true for keysend invoices. + is_keysend BOOLEAN NOT NULL, + + -- Timestamp of when this invoice was created. + created_at TIMESTAMP NOT NULL +); + +CREATE INDEX IF NOT EXISTS invoices_hash_idx ON invoices(hash); +CREATE INDEX IF NOT EXISTS invoices_preimage_idx ON invoices(preimage); +CREATE INDEX IF NOT EXISTS invoices_payment_addr_idx ON invoices(payment_addr); +CREATE INDEX IF NOT EXISTS invoices_state_idx ON invoices(state); +CREATE INDEX IF NOT EXISTS invoices_created_at_idx ON invoices(created_at); + +-- invoice_features contains the feature bits of an invoice. +CREATE TABLE IF NOT EXISTS invoice_features ( + -- The feature bit. + feature INTEGER NOT NULL, + + -- The invoice id this feature belongs to. + invoice_id INTEGER NOT NULL REFERENCES invoices(id), + + -- The feature bit is unique per invoice. + UNIQUE (feature, invoice_id) +); + +CREATE INDEX IF NOT EXISTS invoice_feature_invoice_id_idx ON invoice_features(invoice_id); + +-- invoice_htlcs contains the information of a htlcs related to one of the node +-- invocies. +CREATE TABLE IF NOT EXISTS invoice_htlcs ( + -- The id for this htlc. Used in foreign keys instead of the + -- htlc_id/chan_id combination. + id INTEGER PRIMARY KEY, + + -- The uint64 htlc id. This field is a counter so it is safe to store it as + -- int64 in the database. The application layer must check that there is no + -- overflow when storing/loading this column. + htlc_id BIGINT NOT NULL, + + -- Short chan id indicating the htlc's origin. uint64 stored as text. + chan_id TEXT NOT NULL, + + -- The htlc's amount in millisatoshis. + amount_msat BIGINT NOT NULL, + + -- The total amount expected for the htlcs in a multi-path payment. + total_mpp_msat BIGINT, + + -- The block height at which this htlc was accepted. + accept_height INTEGER NOT NULL, + + -- The timestamp at which this htlc was accepted. + accept_time TIMESTAMP NOT NULL, + + -- The block height at which this htlc expiries. + expiry_height INTEGER NOT NULL, + + -- The htlc state. + state SMALLINT NOT NULL, + + -- Timestamp of when this htlc was resolved (settled/canceled). + resolve_time TIMESTAMP, + + -- The id of the invoice this htlc belongs to. + invoice_id INTEGER NOT NULL REFERENCES invoices(id), + + -- The htlc_id and chan_id identify the htlc. + UNIQUE (htlc_id, chan_id) +); + +CREATE INDEX IF NOT EXISTS invoice_htlc_invoice_id_idx ON invoice_htlcs(invoice_id); + +-- invoice_htlc_custom_records stores the custom key/value pairs that +-- accompanied an htlc. +CREATE TABLE IF NOT EXISTS invoice_htlc_custom_records ( + -- The custom type identifier for this record. + -- The range of values for custom records key is defined in BOLT 01. + key BIGINT NOT NULL, + + -- The custom value for this record. + value BLOB NOT NULL, + + -- The htlc id this record belongs to. + htlc_id BIGINT NOT NULL REFERENCES invoice_htlcs(id) +); + +CREATE INDEX IF NOT EXISTS invoice_htlc_custom_records_htlc_id_idx ON invoice_htlc_custom_records(htlc_id); + +-- invoice_payments contains the information of a settled invoice payment. +CREATE TABLE IF NOT EXISTS invoice_payments ( + -- The id for this invoice payment. Translates to SettleIndex. + id INTEGER PRIMARY KEY, + + -- When the payment was settled. + settled_at TIMESTAMP NOT NULL, + + -- The amount of the payment in millisatoshis. This is the sum of all the + -- the htlcs settled for this payment. + amount_paid_msat BIGINT NOT NULL, + + -- The invoice id this payment is for. + invoice_id INTEGER NOT NULL REFERENCES invoices(id) +); + +CREATE INDEX IF NOT EXISTS invoice_payments_settled_at_idx ON invoice_payments(settled_at); +CREATE INDEX IF NOT EXISTS invoice_payments_invoice_id_idx ON invoice_payments(invoice_id); From 7aa2f390fe1ed945dae5a407c01b7ca11bbc61f7 Mon Sep 17 00:00:00 2001 From: positiveblue Date: Mon, 29 May 2023 19:19:57 -0700 Subject: [PATCH 03/10] sqldb: add invoice queries Set of queries to deal with invoices. A couple of things to take into account: - Because the queries are not rewritten at runtime, we cannot have a generic `INSERT` with different tuples. - Because the queries are not rewritten at runtime, we cannot build one query with only the filters that matter for that queries. The two options are a combinatorial approach (a new query for every permutation) or a generic query using the pattern ``` SELECT * FROM table WHERE ( -- Can be read as: -- Match the filter 1 value if filter_1 != nil column_1 >= sqlc.narg('filter_1') OR sqlc.narg('filter_1') IS NULL ) AND ( column_2 >= sqlc.narg('filter_2') OR sqlc.narg('filter_2') IS NULL ) ... ``` --- sqldb/sqlc/queries/invoices.sql | 196 ++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100644 sqldb/sqlc/queries/invoices.sql diff --git a/sqldb/sqlc/queries/invoices.sql b/sqldb/sqlc/queries/invoices.sql new file mode 100644 index 000000000..335929e05 --- /dev/null +++ b/sqldb/sqlc/queries/invoices.sql @@ -0,0 +1,196 @@ +-- name: InsertInvoice :one +INSERT INTO invoices ( + hash, preimage, memo, amount_msat, cltv_delta, expiry, payment_addr, + payment_request, state, amount_paid_msat, is_amp, is_hodl, is_keysend, + created_at +) VALUES ( + $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14 +) RETURNING id; + +-- name: InsertInvoiceFeature :exec +INSERT INTO invoice_features ( + invoice_id, feature +) VALUES ( + $1, $2 +); + +-- name: GetInvoiceFeatures :many +SELECT * +FROM invoice_features +WHERE invoice_id = $1; + +-- name: DeleteInvoiceFeatures :exec +DELETE +FROM invoice_features +WHERE invoice_id = $1; + +-- This method may return more than one invoice if filter using multiple fields +-- from different invoices. It is the caller's responsibility to ensure that +-- we bubble up an error in those cases. + +-- name: GetInvoice :many +SELECT * +FROM invoices +WHERE ( + id = sqlc.narg('add_index') OR + sqlc.narg('add_index') IS NULL +) AND ( + hash = sqlc.narg('hash') OR + sqlc.narg('hash') IS NULL +) AND ( + preimage = sqlc.narg('preimage') OR + sqlc.narg('preimage') IS NULL +) AND ( + payment_addr = sqlc.narg('payment_addr') OR + sqlc.narg('payment_addr') IS NULL +) +LIMIT 2; + +-- name: FilterInvoices :many +SELECT * +FROM invoices +WHERE ( + id >= sqlc.narg('add_index_get') OR + sqlc.narg('add_index_get') IS NULL +) AND ( + id <= sqlc.narg('add_index_let') OR + sqlc.narg('add_index_let') IS NULL +) AND ( + state = sqlc.narg('state') OR + sqlc.narg('state') IS NULL +) AND ( + created_at >= sqlc.narg('created_after') OR + sqlc.narg('created_after') IS NULL +) AND ( + created_at <= sqlc.narg('created_before') OR + sqlc.narg('created_before') IS NULL +) AND ( + CASE + WHEN sqlc.narg('pending_only')=TRUE THEN (state = 0 OR state = 3) + ELSE TRUE + END +) +ORDER BY + CASE + WHEN sqlc.narg('reverse') = FALSE THEN id + ELSE NULL + END ASC, + CASE + WHEN sqlc.narg('reverse') = TRUE THEN id + ELSE NULL + END DESC +LIMIT @num_limit OFFSET @num_offset; + +-- name: UpdateInvoice :exec +UPDATE invoices +SET preimage=$2, state=$3, amount_paid_msat=$4 +WHERE id=$1; + +-- name: DeleteInvoice :exec +DELETE +FROM invoices +WHERE ( + id = sqlc.narg('add_index') OR + sqlc.narg('add_index') IS NULL +) AND ( + hash = sqlc.narg('hash') OR + sqlc.narg('hash') IS NULL +) AND ( + preimage = sqlc.narg('preimage') OR + sqlc.narg('preimage') IS NULL +) AND ( + payment_addr = sqlc.narg('payment_addr') OR + sqlc.narg('payment_addr') IS NULL +); + +-- name: InsertInvoiceHTLC :exec +INSERT INTO invoice_htlcs ( + htlc_id, chan_id, amount_msat, total_mpp_msat, accept_height, accept_time, + expiry_height, state, resolve_time, invoice_id +) VALUES ( + $1, $2, $3, $4, $5, $6, $7, $8, $9, $10 +); + +-- name: GetInvoiceHTLCs :many +SELECT * +FROM invoice_htlcs +WHERE invoice_id = $1; + +-- name: UpdateInvoiceHTLC :exec +UPDATE invoice_htlcs +SET state=$2, resolve_time=$3 +WHERE id = $1; + +-- name: UpdateInvoiceHTLCs :exec +UPDATE invoice_htlcs +SET state=$2, resolve_time=$3 +WHERE invoice_id = $1 AND resolve_time IS NULL; + + +-- name: DeleteInvoiceHTLC :exec +DELETE +FROM invoice_htlcs +WHERE htlc_id = $1; + +-- name: DeleteInvoiceHTLCs :exec +DELETE +FROM invoice_htlcs +WHERE invoice_id = $1; + +-- name: InsertInvoiceHTLCCustomRecord :exec +INSERT INTO invoice_htlc_custom_records ( + key, value, htlc_id +) VALUES ( + $1, $2, $3 +); + +-- name: GetInvoiceHTLCCustomRecords :many +SELECT ihcr.htlc_id, key, value +FROM invoice_htlcs ih JOIN invoice_htlc_custom_records ihcr ON ih.id=ihcr.htlc_id +WHERE ih.invoice_id = $1; + +-- name: DeleteInvoiceHTLCCustomRecords :exec +WITH htlc_ids AS ( + SELECT ih.id + FROM invoice_htlcs ih JOIN invoice_htlc_custom_records ihcr ON ih.id=ihcr.htlc_id + WHERE ih.invoice_id = $1 +) +DELETE +FROM invoice_htlc_custom_records +WHERE htlc_id IN (SELECT id FROM htlc_ids); + +-- name: InsertInvoicePayment :one +INSERT INTO invoice_payments ( + invoice_id, amount_paid_msat, settled_at +) VALUES ( + $1, $2, $3 +) RETURNING id; + +-- name: GetInvoicePayments :many +SELECT * +FROM invoice_payments +WHERE invoice_id = $1; + +-- name: FilterInvoicePayments :many +SELECT + ip.id AS settle_index, ip.amount_paid_msat, ip.settled_at AS settle_date, + i.* +FROM invoice_payments ip JOIN invoices i ON ip.invoice_id = i.id +WHERE ( + ip.id >= sqlc.narg('settle_index_get') OR + sqlc.narg('settle_index_get') IS NULL +) AND ( + ip.settled_at >= sqlc.narg('settled_after') OR + sqlc.narg('settled_after') IS NULL +) +ORDER BY + CASE + WHEN sqlc.narg('reverse') = FALSE THEN ip.id + ELSE NULL + END ASC, + CASE + WHEN sqlc.narg('reverse') = TRUE THEN ip.id + ELSE NULL + END DESC +LIMIT @num_limit OFFSET @num_offset; + From eda95e6607af0ea330590db308bf1f6b352d33a6 Mon Sep 17 00:00:00 2001 From: positiveblue Date: Mon, 29 May 2023 19:05:46 -0700 Subject: [PATCH 04/10] sqldb: add AMP invoices SQL schema Schema for AMP invocies. AMP invoices can be paid multiple times and each payment to an AMP invoice is identified by a `set_id`. The A in AMP stands for `Atomic`. All the htlcs belonging to the same AMP payment (share the same set_id) will be resolved at the same time with the same result: settled/canceled. AMP invoices do not have an "invoice preimage". Instead, each htcl has its own hash/preimage. When a new htlc is added the hash for that htlc is attached to it. When all the htlcs of a set_id have been received we are able to compute the preimage for each one of them. --- .../migrations/000002_amp_invoices.down.sql | 8 +++ .../migrations/000002_amp_invoices.up.sql | 54 +++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 sqldb/sqlc/migrations/000002_amp_invoices.down.sql create mode 100644 sqldb/sqlc/migrations/000002_amp_invoices.up.sql diff --git a/sqldb/sqlc/migrations/000002_amp_invoices.down.sql b/sqldb/sqlc/migrations/000002_amp_invoices.down.sql new file mode 100644 index 000000000..0167bdeb2 --- /dev/null +++ b/sqldb/sqlc/migrations/000002_amp_invoices.down.sql @@ -0,0 +1,8 @@ +DROP INDEX IF EXISTS amp_htlcs_htlc_id_idx; +DROP INDEX IF EXISTS amp_htlcs_invoice_id_idx; +DROP INDEX IF EXISTS amp_htlcs_set_id_idx; +DROP TABLE IF EXISTS amp_invoice_htlcs; + +DROP INDEX IF EXISTS amp_invoice_payments_invoice_id_idx; +DROP TABLE IF EXISTS amp_invoice_payments; + diff --git a/sqldb/sqlc/migrations/000002_amp_invoices.up.sql b/sqldb/sqlc/migrations/000002_amp_invoices.up.sql new file mode 100644 index 000000000..a4daa8c30 --- /dev/null +++ b/sqldb/sqlc/migrations/000002_amp_invoices.up.sql @@ -0,0 +1,54 @@ +-- amp_invoices_payments +CREATE TABLE IF NOT EXISTS amp_invoice_payments ( + -- The set id identifying the payment. + set_id BLOB PRIMARY KEY, + + -- The state of this amp payment. This matches the state for all the htlcs + -- belonging to this set id. The A in AMP stands for Atomic. + state SMALLINT NOT NULL, + + -- Timestamp of when the first htlc for this payment was accepted. + created_at TIMESTAMP NOT NULL, + + -- If settled, the invoice payment related to this set id. + settled_index INTEGER REFERENCES invoice_payments(id), + + -- The invoice id this set id is related to. + invoice_id INTEGER NOT NULL REFERENCES invoices(id) +); + +CREATE INDEX IF NOT EXISTS amp_invoice_payments_invoice_id_idx ON amp_invoice_payments(invoice_id); + +-- amp_invoice_htlcs contains the complementary information for an htlc related +-- to an AMP invoice. +CREATE TABLE IF NOT EXISTS amp_invoice_htlcs ( + -- The set id identifying the payment this htlc belongs to. + set_id BLOB NOT NULL REFERENCES amp_invoice_payments(set_id), + + -- The id of the htlc this entry blongs to. + htlc_id BIGINT NOT NULL REFERENCES invoice_htlcs(id), + + -- The invoice id this entry is related to. + invoice_id INTEGER NOT NULL REFERENCES invoices(id), + + -- The root share for this amp htlc. + root_share BLOB NOT NULL, + + -- The child index for this amp htlc. + child_index BIGINT NOT NULL, + + -- The htlc-level payment hash. An AMP htlc will carry a different payment + -- hash from the invoice it might be satisfying. They are needed to ensure + -- that we reconstruct the preimage correctly. + hash BLOB NOT NULL, + + -- The HTLC-level preimage that satisfies the AMP htlc's Hash. + -- The preimage will be derived either from secret share reconstruction of + -- the shares in the AMP payload. + preimage BLOB +); + +CREATE INDEX IF NOT EXISTS amp_htlcs_set_id_idx ON amp_invoice_htlcs(set_id); +CREATE INDEX IF NOT EXISTS amp_htlcs_invoice_id_idx ON amp_invoice_htlcs(invoice_id); +CREATE INDEX IF NOT EXISTS amp_htlcs_htlc_id_idx ON amp_invoice_htlcs(htlc_id); + From 6deb916216df915cc4979e71a62aa44192200380 Mon Sep 17 00:00:00 2001 From: positiveblue Date: Tue, 30 May 2023 07:37:17 -0700 Subject: [PATCH 05/10] sqldb: add AMP invoice queries --- sqldb/sqlc/queries/amp_invoices.sql | 79 +++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 sqldb/sqlc/queries/amp_invoices.sql diff --git a/sqldb/sqlc/queries/amp_invoices.sql b/sqldb/sqlc/queries/amp_invoices.sql new file mode 100644 index 000000000..d965de768 --- /dev/null +++ b/sqldb/sqlc/queries/amp_invoices.sql @@ -0,0 +1,79 @@ +-- name: InsertAMPInvoicePayment :exec +INSERT INTO amp_invoice_payments ( + set_id, state, created_at, settled_index, invoice_id +) VALUES ( + $1, $2, $3, $4, $5 +); + +-- name: SelectAMPInvoicePayments :many +SELECT aip.*, ip.* +FROM amp_invoice_payments aip LEFT JOIN invoice_payments ip ON aip.settled_index = ip.id +WHERE ( + set_id = sqlc.narg('set_id') OR + sqlc.narg('set_id') IS NULL +) AND ( + aip.settled_index = sqlc.narg('settled_index') OR + sqlc.narg('settled_index') IS NULL +) AND ( + aip.invoice_id = sqlc.narg('invoice_id') OR + sqlc.narg('invoice_id') IS NULL +); + +-- name: UpdateAMPPayment :exec +UPDATE amp_invoice_payments +SET state = $1, settled_index = $2 +WHERE state = 0 AND ( + set_id = sqlc.narg('set_id') OR + sqlc.narg('set_id') IS NULL +) AND ( + invoice_id = sqlc.narg('invoice_id') OR + sqlc.narg('invoice_id') IS NULL +); + +-- name: InsertAMPInvoiceHTLC :exec +INSERT INTO amp_invoice_htlcs ( + set_id, htlc_id, root_share, child_index, hash, preimage +) VALUES ( + $1, $2, $3, $4, $5, $6 +); + +-- name: GetAMPInvoiceHTLCsBySetID :many +SELECT * +FROM amp_invoice_htlcs +WHERE set_id = $1; + +-- name: GetAMPInvoiceHTLCsByInvoiceID :many +SELECT * +FROM amp_invoice_htlcs +WHERE invoice_id = $1; + +-- name: GetSetIDHTLCsCustomRecords :many +SELECT ihcr.htlc_id, key, value +FROM amp_invoice_htlcs aih JOIN invoice_htlc_custom_records ihcr ON aih.id=ihcr.htlc_id +WHERE aih.set_id = $1; + +-- name: UpdateAMPInvoiceHTLC :exec +UPDATE amp_invoice_htlcs +SET preimage = $1 +WHERE htlc_id = $2; + +-- name: DeleteAMPHTLCCustomRecords :exec +WITH htlc_ids AS ( + SELECT htlc_id + FROM amp_invoice_htlcs + WHERE invoice_id = $1 +) +DELETE +FROM invoice_htlc_custom_records +WHERE htlc_id IN (SELECT id FROM htlc_ids); + +-- name: DeleteAMPHTLCs :exec +DELETE +FROM amp_invoice_htlcs +WHERE invoice_id = $1; + +-- name: DeleteAMPInvoiceHTLC :exec +DELETE +FROM amp_invoice_htlcs +WHERE set_id = $1; + From fb16287b31f8855ab47482b92aa7ac9093a7c6fb Mon Sep 17 00:00:00 2001 From: positiveblue Date: Mon, 5 Jun 2023 21:12:04 -0700 Subject: [PATCH 06/10] sqldb: add invoice events SQL schema --- .../migrations/000003_invoice_events.down.sql | 9 +++ .../migrations/000003_invoice_events.up.sql | 59 +++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 sqldb/sqlc/migrations/000003_invoice_events.down.sql create mode 100644 sqldb/sqlc/migrations/000003_invoice_events.up.sql diff --git a/sqldb/sqlc/migrations/000003_invoice_events.down.sql b/sqldb/sqlc/migrations/000003_invoice_events.down.sql new file mode 100644 index 000000000..66e554e24 --- /dev/null +++ b/sqldb/sqlc/migrations/000003_invoice_events.down.sql @@ -0,0 +1,9 @@ +DROP TABLE IF EXISTS invoice_events; + +DROP INDEX IF EXISTS invoice_events_created_at_idx; +DROP INDEX IF EXISTS invoice_events_invoice_id_idx; +DROP INDEX IF EXISTS invoice_events_htlc_id_idx; +DROP INDEX IF EXISTS invoice_events_set_id_idx; +DROP INDEX IF EXISTS invoice_events_event_type_idx; + +DROP TABLE IF EXISTS invoice_event_types; diff --git a/sqldb/sqlc/migrations/000003_invoice_events.up.sql b/sqldb/sqlc/migrations/000003_invoice_events.up.sql new file mode 100644 index 000000000..47d2a91d0 --- /dev/null +++ b/sqldb/sqlc/migrations/000003_invoice_events.up.sql @@ -0,0 +1,59 @@ +-- invoice_event_types stores the different types of events that can be emitted +-- for invoices. +CREATE TABLE IF NOT EXISTS invoice_event_types( + id INTEGER PRIMARY KEY, + + description TEXT NOT NULL +); + +-- invoice_events stores all events related to the node invoices. +CREATE TABLE IF NOT EXISTS invoice_events ( + id INTEGER PRIMARY KEY, + + -- created_at is the creation time of this event. + created_at TIMESTAMP NOT NULL, + + -- invoice_id is the reference to the invoice this event was emitted for. + invoice_id INTEGER NOT NULL REFERENCES invoices(id), + + -- htlc_id is the reference to the htlc this event was emitted for, may be + -- null. + htlc_id BIGINT REFERENCES invoice_htlcs(htlc_id), + + -- set_id is the reference to the set_id this event was emitted for, may be + -- null. + set_id BLOB NOT NULL REFERENCES amp_invoice_payments(set_id), + + -- event_type is the type of this event. + event_type INTEGER NOT NULL REFERENCES invoice_event_types(id), + + -- event_metadata is a TLV encoding any relevant information for this kind + -- of events. + event_metadata BLOB +); + +CREATE INDEX IF NOT EXISTS invoice_events_created_at_idx ON invoice_events(created_at); +CREATE INDEX IF NOT EXISTS invoice_events_invoice_id_idx ON invoice_events(invoice_id); +CREATE INDEX IF NOT EXISTS invoice_events_htlc_id_idx ON invoice_events(htlc_id); +CREATE INDEX IF NOT EXISTS invoice_events_set_id_idx ON invoice_events(set_id); +CREATE INDEX IF NOT EXISTS invoice_events_event_type_idx ON invoice_events(event_type); + + +-- invoice_event_types defines the different types of events that can be emitted +-- for an invoice. +INSERT INTO invoice_event_types (id, description) +VALUES + -- invoice_created is the event emitted when an invoice is created. + (0, 'invoice_created'), + -- invoice_canceled is the event emitted when an invoice is canceled. + (1, "invoice_canceled"), + -- invoice_settled is the event emitted when an invoice is settled. + (2, "invoice_settled"), + -- setid_created is the event emitted when the first htlc for the set_id is + -- received. + (3, "setid_created"), + -- setid_canceled is the event emitted when the set_id is canceled. + (4, "setid_canceled"), + -- setid_settled is the event emitted when the set_id is settled. + (5, "setid_settled"); + From 877b71136065a179ef946755fe305fb317528b49 Mon Sep 17 00:00:00 2001 From: positiveblue Date: Mon, 5 Jun 2023 21:17:00 -0700 Subject: [PATCH 07/10] sqldb: add invoice event queries --- sqldb/sqlc/queries/invoice_events.sql | 35 +++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 sqldb/sqlc/queries/invoice_events.sql diff --git a/sqldb/sqlc/queries/invoice_events.sql b/sqldb/sqlc/queries/invoice_events.sql new file mode 100644 index 000000000..4216a2513 --- /dev/null +++ b/sqldb/sqlc/queries/invoice_events.sql @@ -0,0 +1,35 @@ +-- name: InsertInvoiceEvent :exec +INSERT INTO invoice_events ( + created_at, invoice_id, htlc_id, set_id, event_type, event_metadata +) VALUES ( + $1, $2, $3, $4, $5, $6 +); + +-- name: SelectInvoiceEvents :many +SELECT * +FROM invoice_events +WHERE ( + invoice_id = sqlc.narg('invoice_id') OR + sqlc.narg('invoice_id') IS NULL +) AND ( + htlc_id = sqlc.narg('htlc_id') OR + sqlc.narg('htlc_id') IS NULL +) AND ( + set_id = sqlc.narg('set_id') OR + sqlc.narg('set_id') IS NULL +) AND ( + event_type = sqlc.narg('event_type') OR + sqlc.narg('event_type') IS NULL +) AND ( + created_at >= sqlc.narg('created_after') OR + sqlc.narg('created_after') IS NULL +) AND ( + created_at <= sqlc.narg('created_before') OR + sqlc.narg('created_before') IS NULL +) +LIMIT @num_limit OFFSET @num_offset; + +-- name: DeleteInvoiceEvents :exec +DELETE +FROM invoice_events +WHERE invoice_id = $1; From 730db7ee8c7a5d2257c4fff3d914c9dcb96f156f Mon Sep 17 00:00:00 2001 From: positiveblue Date: Tue, 30 May 2023 07:37:48 -0700 Subject: [PATCH 08/10] sqlc: generate go code from SQL run `make sqlc` All the code in this commit is auto-generated. --- sqldb/sqlc/amp_invoices.sql.go | 326 ++++++++++++++ sqldb/sqlc/db.go | 31 ++ sqldb/sqlc/invoice_events.sql.go | 128 ++++++ sqldb/sqlc/invoices.sql.go | 709 +++++++++++++++++++++++++++++++ sqldb/sqlc/models.go | 93 ++++ sqldb/sqlc/querier.go | 51 +++ 6 files changed, 1338 insertions(+) create mode 100644 sqldb/sqlc/amp_invoices.sql.go create mode 100644 sqldb/sqlc/db.go create mode 100644 sqldb/sqlc/invoice_events.sql.go create mode 100644 sqldb/sqlc/invoices.sql.go create mode 100644 sqldb/sqlc/models.go create mode 100644 sqldb/sqlc/querier.go diff --git a/sqldb/sqlc/amp_invoices.sql.go b/sqldb/sqlc/amp_invoices.sql.go new file mode 100644 index 000000000..c803a8307 --- /dev/null +++ b/sqldb/sqlc/amp_invoices.sql.go @@ -0,0 +1,326 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.18.0 +// source: amp_invoices.sql + +package sqlc + +import ( + "context" + "database/sql" + "time" +) + +const deleteAMPHTLCCustomRecords = `-- name: DeleteAMPHTLCCustomRecords :exec +WITH htlc_ids AS ( + SELECT htlc_id + FROM amp_invoice_htlcs + WHERE invoice_id = $1 +) +DELETE +FROM invoice_htlc_custom_records +WHERE htlc_id IN (SELECT id FROM htlc_ids) +` + +func (q *Queries) DeleteAMPHTLCCustomRecords(ctx context.Context, invoiceID int32) error { + _, err := q.db.ExecContext(ctx, deleteAMPHTLCCustomRecords, invoiceID) + return err +} + +const deleteAMPHTLCs = `-- name: DeleteAMPHTLCs :exec +DELETE +FROM amp_invoice_htlcs +WHERE invoice_id = $1 +` + +func (q *Queries) DeleteAMPHTLCs(ctx context.Context, invoiceID int32) error { + _, err := q.db.ExecContext(ctx, deleteAMPHTLCs, invoiceID) + return err +} + +const deleteAMPInvoiceHTLC = `-- name: DeleteAMPInvoiceHTLC :exec +DELETE +FROM amp_invoice_htlcs +WHERE set_id = $1 +` + +func (q *Queries) DeleteAMPInvoiceHTLC(ctx context.Context, setID []byte) error { + _, err := q.db.ExecContext(ctx, deleteAMPInvoiceHTLC, setID) + return err +} + +const getAMPInvoiceHTLCsByInvoiceID = `-- name: GetAMPInvoiceHTLCsByInvoiceID :many +SELECT set_id, htlc_id, invoice_id, root_share, child_index, hash, preimage +FROM amp_invoice_htlcs +WHERE invoice_id = $1 +` + +func (q *Queries) GetAMPInvoiceHTLCsByInvoiceID(ctx context.Context, invoiceID int32) ([]AmpInvoiceHtlc, error) { + rows, err := q.db.QueryContext(ctx, getAMPInvoiceHTLCsByInvoiceID, invoiceID) + if err != nil { + return nil, err + } + defer rows.Close() + var items []AmpInvoiceHtlc + for rows.Next() { + var i AmpInvoiceHtlc + if err := rows.Scan( + &i.SetID, + &i.HtlcID, + &i.InvoiceID, + &i.RootShare, + &i.ChildIndex, + &i.Hash, + &i.Preimage, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const getAMPInvoiceHTLCsBySetID = `-- name: GetAMPInvoiceHTLCsBySetID :many +SELECT set_id, htlc_id, invoice_id, root_share, child_index, hash, preimage +FROM amp_invoice_htlcs +WHERE set_id = $1 +` + +func (q *Queries) GetAMPInvoiceHTLCsBySetID(ctx context.Context, setID []byte) ([]AmpInvoiceHtlc, error) { + rows, err := q.db.QueryContext(ctx, getAMPInvoiceHTLCsBySetID, setID) + if err != nil { + return nil, err + } + defer rows.Close() + var items []AmpInvoiceHtlc + for rows.Next() { + var i AmpInvoiceHtlc + if err := rows.Scan( + &i.SetID, + &i.HtlcID, + &i.InvoiceID, + &i.RootShare, + &i.ChildIndex, + &i.Hash, + &i.Preimage, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const getSetIDHTLCsCustomRecords = `-- name: GetSetIDHTLCsCustomRecords :many +SELECT ihcr.htlc_id, key, value +FROM amp_invoice_htlcs aih JOIN invoice_htlc_custom_records ihcr ON aih.id=ihcr.htlc_id +WHERE aih.set_id = $1 +` + +type GetSetIDHTLCsCustomRecordsRow struct { + HtlcID int64 + Key int64 + Value []byte +} + +func (q *Queries) GetSetIDHTLCsCustomRecords(ctx context.Context, setID []byte) ([]GetSetIDHTLCsCustomRecordsRow, error) { + rows, err := q.db.QueryContext(ctx, getSetIDHTLCsCustomRecords, setID) + if err != nil { + return nil, err + } + defer rows.Close() + var items []GetSetIDHTLCsCustomRecordsRow + for rows.Next() { + var i GetSetIDHTLCsCustomRecordsRow + if err := rows.Scan(&i.HtlcID, &i.Key, &i.Value); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const insertAMPInvoiceHTLC = `-- name: InsertAMPInvoiceHTLC :exec +INSERT INTO amp_invoice_htlcs ( + set_id, htlc_id, root_share, child_index, hash, preimage +) VALUES ( + $1, $2, $3, $4, $5, $6 +) +` + +type InsertAMPInvoiceHTLCParams struct { + SetID []byte + HtlcID int64 + RootShare []byte + ChildIndex int64 + Hash []byte + Preimage []byte +} + +func (q *Queries) InsertAMPInvoiceHTLC(ctx context.Context, arg InsertAMPInvoiceHTLCParams) error { + _, err := q.db.ExecContext(ctx, insertAMPInvoiceHTLC, + arg.SetID, + arg.HtlcID, + arg.RootShare, + arg.ChildIndex, + arg.Hash, + arg.Preimage, + ) + return err +} + +const insertAMPInvoicePayment = `-- name: InsertAMPInvoicePayment :exec +INSERT INTO amp_invoice_payments ( + set_id, state, created_at, settled_index, invoice_id +) VALUES ( + $1, $2, $3, $4, $5 +) +` + +type InsertAMPInvoicePaymentParams struct { + SetID []byte + State int16 + CreatedAt time.Time + SettledIndex sql.NullInt32 + InvoiceID int32 +} + +func (q *Queries) InsertAMPInvoicePayment(ctx context.Context, arg InsertAMPInvoicePaymentParams) error { + _, err := q.db.ExecContext(ctx, insertAMPInvoicePayment, + arg.SetID, + arg.State, + arg.CreatedAt, + arg.SettledIndex, + arg.InvoiceID, + ) + return err +} + +const selectAMPInvoicePayments = `-- name: SelectAMPInvoicePayments :many +SELECT aip.set_id, aip.state, aip.created_at, aip.settled_index, aip.invoice_id, ip.id, ip.settled_at, ip.amount_paid_msat, ip.invoice_id +FROM amp_invoice_payments aip LEFT JOIN invoice_payments ip ON aip.settled_index = ip.id +WHERE ( + set_id = $1 OR + $1 IS NULL +) AND ( + aip.settled_index = $2 OR + $2 IS NULL +) AND ( + aip.invoice_id = $3 OR + $3 IS NULL +) +` + +type SelectAMPInvoicePaymentsParams struct { + SetID []byte + SettledIndex sql.NullInt32 + InvoiceID sql.NullInt32 +} + +type SelectAMPInvoicePaymentsRow struct { + SetID []byte + State int16 + CreatedAt time.Time + SettledIndex sql.NullInt32 + InvoiceID int32 + ID sql.NullInt32 + SettledAt sql.NullTime + AmountPaidMsat sql.NullInt64 + InvoiceID_2 sql.NullInt32 +} + +func (q *Queries) SelectAMPInvoicePayments(ctx context.Context, arg SelectAMPInvoicePaymentsParams) ([]SelectAMPInvoicePaymentsRow, error) { + rows, err := q.db.QueryContext(ctx, selectAMPInvoicePayments, arg.SetID, arg.SettledIndex, arg.InvoiceID) + if err != nil { + return nil, err + } + defer rows.Close() + var items []SelectAMPInvoicePaymentsRow + for rows.Next() { + var i SelectAMPInvoicePaymentsRow + if err := rows.Scan( + &i.SetID, + &i.State, + &i.CreatedAt, + &i.SettledIndex, + &i.InvoiceID, + &i.ID, + &i.SettledAt, + &i.AmountPaidMsat, + &i.InvoiceID_2, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const updateAMPInvoiceHTLC = `-- name: UpdateAMPInvoiceHTLC :exec +UPDATE amp_invoice_htlcs +SET preimage = $1 +WHERE htlc_id = $2 +` + +type UpdateAMPInvoiceHTLCParams struct { + Preimage []byte + HtlcID int64 +} + +func (q *Queries) UpdateAMPInvoiceHTLC(ctx context.Context, arg UpdateAMPInvoiceHTLCParams) error { + _, err := q.db.ExecContext(ctx, updateAMPInvoiceHTLC, arg.Preimage, arg.HtlcID) + return err +} + +const updateAMPPayment = `-- name: UpdateAMPPayment :exec +UPDATE amp_invoice_payments +SET state = $1, settled_index = $2 +WHERE state = 0 AND ( + set_id = $3 OR + $3 IS NULL +) AND ( + invoice_id = $4 OR + $4 IS NULL +) +` + +type UpdateAMPPaymentParams struct { + State int16 + SettledIndex sql.NullInt32 + SetID []byte + InvoiceID sql.NullInt32 +} + +func (q *Queries) UpdateAMPPayment(ctx context.Context, arg UpdateAMPPaymentParams) error { + _, err := q.db.ExecContext(ctx, updateAMPPayment, + arg.State, + arg.SettledIndex, + arg.SetID, + arg.InvoiceID, + ) + return err +} diff --git a/sqldb/sqlc/db.go b/sqldb/sqlc/db.go new file mode 100644 index 000000000..9848f3e6a --- /dev/null +++ b/sqldb/sqlc/db.go @@ -0,0 +1,31 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.18.0 + +package sqlc + +import ( + "context" + "database/sql" +) + +type DBTX interface { + ExecContext(context.Context, string, ...interface{}) (sql.Result, error) + PrepareContext(context.Context, string) (*sql.Stmt, error) + QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error) + QueryRowContext(context.Context, string, ...interface{}) *sql.Row +} + +func New(db DBTX) *Queries { + return &Queries{db: db} +} + +type Queries struct { + db DBTX +} + +func (q *Queries) WithTx(tx *sql.Tx) *Queries { + return &Queries{ + db: tx, + } +} diff --git a/sqldb/sqlc/invoice_events.sql.go b/sqldb/sqlc/invoice_events.sql.go new file mode 100644 index 000000000..054d9091c --- /dev/null +++ b/sqldb/sqlc/invoice_events.sql.go @@ -0,0 +1,128 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.18.0 +// source: invoice_events.sql + +package sqlc + +import ( + "context" + "database/sql" + "time" +) + +const deleteInvoiceEvents = `-- name: DeleteInvoiceEvents :exec +DELETE +FROM invoice_events +WHERE invoice_id = $1 +` + +func (q *Queries) DeleteInvoiceEvents(ctx context.Context, invoiceID int32) error { + _, err := q.db.ExecContext(ctx, deleteInvoiceEvents, invoiceID) + return err +} + +const insertInvoiceEvent = `-- name: InsertInvoiceEvent :exec +INSERT INTO invoice_events ( + created_at, invoice_id, htlc_id, set_id, event_type, event_metadata +) VALUES ( + $1, $2, $3, $4, $5, $6 +) +` + +type InsertInvoiceEventParams struct { + CreatedAt time.Time + InvoiceID int32 + HtlcID sql.NullInt64 + SetID []byte + EventType int32 + EventMetadata []byte +} + +func (q *Queries) InsertInvoiceEvent(ctx context.Context, arg InsertInvoiceEventParams) error { + _, err := q.db.ExecContext(ctx, insertInvoiceEvent, + arg.CreatedAt, + arg.InvoiceID, + arg.HtlcID, + arg.SetID, + arg.EventType, + arg.EventMetadata, + ) + return err +} + +const selectInvoiceEvents = `-- name: SelectInvoiceEvents :many +SELECT id, created_at, invoice_id, htlc_id, set_id, event_type, event_metadata +FROM invoice_events +WHERE ( + invoice_id = $1 OR + $1 IS NULL +) AND ( + htlc_id = $2 OR + $2 IS NULL +) AND ( + set_id = $3 OR + $3 IS NULL +) AND ( + event_type = $4 OR + $4 IS NULL +) AND ( + created_at >= $5 OR + $5 IS NULL +) AND ( + created_at <= $6 OR + $6 IS NULL +) +LIMIT $8 OFFSET $7 +` + +type SelectInvoiceEventsParams struct { + InvoiceID sql.NullInt32 + HtlcID sql.NullInt64 + SetID []byte + EventType sql.NullInt32 + CreatedAfter sql.NullTime + CreatedBefore sql.NullTime + NumOffset int32 + NumLimit int32 +} + +func (q *Queries) SelectInvoiceEvents(ctx context.Context, arg SelectInvoiceEventsParams) ([]InvoiceEvent, error) { + rows, err := q.db.QueryContext(ctx, selectInvoiceEvents, + arg.InvoiceID, + arg.HtlcID, + arg.SetID, + arg.EventType, + arg.CreatedAfter, + arg.CreatedBefore, + arg.NumOffset, + arg.NumLimit, + ) + if err != nil { + return nil, err + } + defer rows.Close() + var items []InvoiceEvent + for rows.Next() { + var i InvoiceEvent + if err := rows.Scan( + &i.ID, + &i.CreatedAt, + &i.InvoiceID, + &i.HtlcID, + &i.SetID, + &i.EventType, + &i.EventMetadata, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} diff --git a/sqldb/sqlc/invoices.sql.go b/sqldb/sqlc/invoices.sql.go new file mode 100644 index 000000000..fa8d9c294 --- /dev/null +++ b/sqldb/sqlc/invoices.sql.go @@ -0,0 +1,709 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.18.0 +// source: invoices.sql + +package sqlc + +import ( + "context" + "database/sql" + "time" +) + +const deleteInvoice = `-- name: DeleteInvoice :exec +DELETE +FROM invoices +WHERE ( + id = $1 OR + $1 IS NULL +) AND ( + hash = $2 OR + $2 IS NULL +) AND ( + preimage = $3 OR + $3 IS NULL +) AND ( + payment_addr = $4 OR + $4 IS NULL +) +` + +type DeleteInvoiceParams struct { + AddIndex sql.NullInt32 + Hash []byte + Preimage []byte + PaymentAddr []byte +} + +func (q *Queries) DeleteInvoice(ctx context.Context, arg DeleteInvoiceParams) error { + _, err := q.db.ExecContext(ctx, deleteInvoice, + arg.AddIndex, + arg.Hash, + arg.Preimage, + arg.PaymentAddr, + ) + return err +} + +const deleteInvoiceFeatures = `-- name: DeleteInvoiceFeatures :exec +DELETE +FROM invoice_features +WHERE invoice_id = $1 +` + +func (q *Queries) DeleteInvoiceFeatures(ctx context.Context, invoiceID int32) error { + _, err := q.db.ExecContext(ctx, deleteInvoiceFeatures, invoiceID) + return err +} + +const deleteInvoiceHTLC = `-- name: DeleteInvoiceHTLC :exec +DELETE +FROM invoice_htlcs +WHERE htlc_id = $1 +` + +func (q *Queries) DeleteInvoiceHTLC(ctx context.Context, htlcID int64) error { + _, err := q.db.ExecContext(ctx, deleteInvoiceHTLC, htlcID) + return err +} + +const deleteInvoiceHTLCCustomRecords = `-- name: DeleteInvoiceHTLCCustomRecords :exec +WITH htlc_ids AS ( + SELECT ih.id + FROM invoice_htlcs ih JOIN invoice_htlc_custom_records ihcr ON ih.id=ihcr.htlc_id + WHERE ih.invoice_id = $1 +) +DELETE +FROM invoice_htlc_custom_records +WHERE htlc_id IN (SELECT id FROM htlc_ids) +` + +func (q *Queries) DeleteInvoiceHTLCCustomRecords(ctx context.Context, invoiceID int32) error { + _, err := q.db.ExecContext(ctx, deleteInvoiceHTLCCustomRecords, invoiceID) + return err +} + +const deleteInvoiceHTLCs = `-- name: DeleteInvoiceHTLCs :exec +DELETE +FROM invoice_htlcs +WHERE invoice_id = $1 +` + +func (q *Queries) DeleteInvoiceHTLCs(ctx context.Context, invoiceID int32) error { + _, err := q.db.ExecContext(ctx, deleteInvoiceHTLCs, invoiceID) + return err +} + +const filterInvoicePayments = `-- name: FilterInvoicePayments :many +SELECT + ip.id AS settle_index, ip.amount_paid_msat, ip.settled_at AS settle_date, + i.id, i.hash, i.preimage, i.memo, i.amount_msat, i.cltv_delta, i.expiry, i.payment_addr, i.payment_request, i.state, i.amount_paid_msat, i.is_amp, i.is_hodl, i.is_keysend, i.created_at +FROM invoice_payments ip JOIN invoices i ON ip.invoice_id = i.id +WHERE ( + ip.id >= $1 OR + $1 IS NULL +) AND ( + ip.settled_at >= $2 OR + $2 IS NULL +) +ORDER BY + CASE + WHEN $3 = FALSE THEN ip.id + ELSE NULL + END ASC, + CASE + WHEN $3 = TRUE THEN ip.id + ELSE NULL + END DESC +LIMIT $5 OFFSET $4 +` + +type FilterInvoicePaymentsParams struct { + SettleIndexGet sql.NullInt32 + SettledAfter sql.NullTime + Reverse interface{} + NumOffset int32 + NumLimit int32 +} + +type FilterInvoicePaymentsRow struct { + SettleIndex int32 + AmountPaidMsat int64 + SettleDate time.Time + ID int32 + Hash []byte + Preimage []byte + Memo sql.NullString + AmountMsat int64 + CltvDelta sql.NullInt32 + Expiry int32 + PaymentAddr []byte + PaymentRequest sql.NullString + State int16 + AmountPaidMsat_2 int64 + IsAmp bool + IsHodl bool + IsKeysend bool + CreatedAt time.Time +} + +func (q *Queries) FilterInvoicePayments(ctx context.Context, arg FilterInvoicePaymentsParams) ([]FilterInvoicePaymentsRow, error) { + rows, err := q.db.QueryContext(ctx, filterInvoicePayments, + arg.SettleIndexGet, + arg.SettledAfter, + arg.Reverse, + arg.NumOffset, + arg.NumLimit, + ) + if err != nil { + return nil, err + } + defer rows.Close() + var items []FilterInvoicePaymentsRow + for rows.Next() { + var i FilterInvoicePaymentsRow + if err := rows.Scan( + &i.SettleIndex, + &i.AmountPaidMsat, + &i.SettleDate, + &i.ID, + &i.Hash, + &i.Preimage, + &i.Memo, + &i.AmountMsat, + &i.CltvDelta, + &i.Expiry, + &i.PaymentAddr, + &i.PaymentRequest, + &i.State, + &i.AmountPaidMsat_2, + &i.IsAmp, + &i.IsHodl, + &i.IsKeysend, + &i.CreatedAt, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const filterInvoices = `-- name: FilterInvoices :many +SELECT id, hash, preimage, memo, amount_msat, cltv_delta, expiry, payment_addr, payment_request, state, amount_paid_msat, is_amp, is_hodl, is_keysend, created_at +FROM invoices +WHERE ( + id >= $1 OR + $1 IS NULL +) AND ( + id <= $2 OR + $2 IS NULL +) AND ( + state = $3 OR + $3 IS NULL +) AND ( + created_at >= $4 OR + $4 IS NULL +) AND ( + created_at <= $5 OR + $5 IS NULL +) AND ( + CASE + WHEN $6=TRUE THEN (state = 0 OR state = 3) + ELSE TRUE + END +) +ORDER BY + CASE + WHEN $7 = FALSE THEN id + ELSE NULL + END ASC, + CASE + WHEN $7 = TRUE THEN id + ELSE NULL + END DESC +LIMIT $9 OFFSET $8 +` + +type FilterInvoicesParams struct { + AddIndexGet sql.NullInt32 + AddIndexLet sql.NullInt32 + State sql.NullInt16 + CreatedAfter sql.NullTime + CreatedBefore sql.NullTime + PendingOnly interface{} + Reverse interface{} + NumOffset int32 + NumLimit int32 +} + +func (q *Queries) FilterInvoices(ctx context.Context, arg FilterInvoicesParams) ([]Invoice, error) { + rows, err := q.db.QueryContext(ctx, filterInvoices, + arg.AddIndexGet, + arg.AddIndexLet, + arg.State, + arg.CreatedAfter, + arg.CreatedBefore, + arg.PendingOnly, + arg.Reverse, + arg.NumOffset, + arg.NumLimit, + ) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Invoice + for rows.Next() { + var i Invoice + if err := rows.Scan( + &i.ID, + &i.Hash, + &i.Preimage, + &i.Memo, + &i.AmountMsat, + &i.CltvDelta, + &i.Expiry, + &i.PaymentAddr, + &i.PaymentRequest, + &i.State, + &i.AmountPaidMsat, + &i.IsAmp, + &i.IsHodl, + &i.IsKeysend, + &i.CreatedAt, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const getInvoice = `-- name: GetInvoice :many + +SELECT id, hash, preimage, memo, amount_msat, cltv_delta, expiry, payment_addr, payment_request, state, amount_paid_msat, is_amp, is_hodl, is_keysend, created_at +FROM invoices +WHERE ( + id = $1 OR + $1 IS NULL +) AND ( + hash = $2 OR + $2 IS NULL +) AND ( + preimage = $3 OR + $3 IS NULL +) AND ( + payment_addr = $4 OR + $4 IS NULL +) +LIMIT 2 +` + +type GetInvoiceParams struct { + AddIndex sql.NullInt32 + Hash []byte + Preimage []byte + PaymentAddr []byte +} + +// This method may return more than one invoice if filter using multiple fields +// from different invoices. It is the caller's responsibility to ensure that +// we bubble up an error in those cases. +func (q *Queries) GetInvoice(ctx context.Context, arg GetInvoiceParams) ([]Invoice, error) { + rows, err := q.db.QueryContext(ctx, getInvoice, + arg.AddIndex, + arg.Hash, + arg.Preimage, + arg.PaymentAddr, + ) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Invoice + for rows.Next() { + var i Invoice + if err := rows.Scan( + &i.ID, + &i.Hash, + &i.Preimage, + &i.Memo, + &i.AmountMsat, + &i.CltvDelta, + &i.Expiry, + &i.PaymentAddr, + &i.PaymentRequest, + &i.State, + &i.AmountPaidMsat, + &i.IsAmp, + &i.IsHodl, + &i.IsKeysend, + &i.CreatedAt, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const getInvoiceFeatures = `-- name: GetInvoiceFeatures :many +SELECT feature, invoice_id +FROM invoice_features +WHERE invoice_id = $1 +` + +func (q *Queries) GetInvoiceFeatures(ctx context.Context, invoiceID int32) ([]InvoiceFeature, error) { + rows, err := q.db.QueryContext(ctx, getInvoiceFeatures, invoiceID) + if err != nil { + return nil, err + } + defer rows.Close() + var items []InvoiceFeature + for rows.Next() { + var i InvoiceFeature + if err := rows.Scan(&i.Feature, &i.InvoiceID); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const getInvoiceHTLCCustomRecords = `-- name: GetInvoiceHTLCCustomRecords :many +SELECT ihcr.htlc_id, key, value +FROM invoice_htlcs ih JOIN invoice_htlc_custom_records ihcr ON ih.id=ihcr.htlc_id +WHERE ih.invoice_id = $1 +` + +type GetInvoiceHTLCCustomRecordsRow struct { + HtlcID int64 + Key int64 + Value []byte +} + +func (q *Queries) GetInvoiceHTLCCustomRecords(ctx context.Context, invoiceID int32) ([]GetInvoiceHTLCCustomRecordsRow, error) { + rows, err := q.db.QueryContext(ctx, getInvoiceHTLCCustomRecords, invoiceID) + if err != nil { + return nil, err + } + defer rows.Close() + var items []GetInvoiceHTLCCustomRecordsRow + for rows.Next() { + var i GetInvoiceHTLCCustomRecordsRow + if err := rows.Scan(&i.HtlcID, &i.Key, &i.Value); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const getInvoiceHTLCs = `-- name: GetInvoiceHTLCs :many +SELECT id, htlc_id, chan_id, amount_msat, total_mpp_msat, accept_height, accept_time, expiry_height, state, resolve_time, invoice_id +FROM invoice_htlcs +WHERE invoice_id = $1 +` + +func (q *Queries) GetInvoiceHTLCs(ctx context.Context, invoiceID int32) ([]InvoiceHtlc, error) { + rows, err := q.db.QueryContext(ctx, getInvoiceHTLCs, invoiceID) + if err != nil { + return nil, err + } + defer rows.Close() + var items []InvoiceHtlc + for rows.Next() { + var i InvoiceHtlc + if err := rows.Scan( + &i.ID, + &i.HtlcID, + &i.ChanID, + &i.AmountMsat, + &i.TotalMppMsat, + &i.AcceptHeight, + &i.AcceptTime, + &i.ExpiryHeight, + &i.State, + &i.ResolveTime, + &i.InvoiceID, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const getInvoicePayments = `-- name: GetInvoicePayments :many +SELECT id, settled_at, amount_paid_msat, invoice_id +FROM invoice_payments +WHERE invoice_id = $1 +` + +func (q *Queries) GetInvoicePayments(ctx context.Context, invoiceID int32) ([]InvoicePayment, error) { + rows, err := q.db.QueryContext(ctx, getInvoicePayments, invoiceID) + if err != nil { + return nil, err + } + defer rows.Close() + var items []InvoicePayment + for rows.Next() { + var i InvoicePayment + if err := rows.Scan( + &i.ID, + &i.SettledAt, + &i.AmountPaidMsat, + &i.InvoiceID, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const insertInvoice = `-- name: InsertInvoice :one +INSERT INTO invoices ( + hash, preimage, memo, amount_msat, cltv_delta, expiry, payment_addr, + payment_request, state, amount_paid_msat, is_amp, is_hodl, is_keysend, + created_at +) VALUES ( + $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14 +) RETURNING id +` + +type InsertInvoiceParams struct { + Hash []byte + Preimage []byte + Memo sql.NullString + AmountMsat int64 + CltvDelta sql.NullInt32 + Expiry int32 + PaymentAddr []byte + PaymentRequest sql.NullString + State int16 + AmountPaidMsat int64 + IsAmp bool + IsHodl bool + IsKeysend bool + CreatedAt time.Time +} + +func (q *Queries) InsertInvoice(ctx context.Context, arg InsertInvoiceParams) (int32, error) { + row := q.db.QueryRowContext(ctx, insertInvoice, + arg.Hash, + arg.Preimage, + arg.Memo, + arg.AmountMsat, + arg.CltvDelta, + arg.Expiry, + arg.PaymentAddr, + arg.PaymentRequest, + arg.State, + arg.AmountPaidMsat, + arg.IsAmp, + arg.IsHodl, + arg.IsKeysend, + arg.CreatedAt, + ) + var id int32 + err := row.Scan(&id) + return id, err +} + +const insertInvoiceFeature = `-- name: InsertInvoiceFeature :exec +INSERT INTO invoice_features ( + invoice_id, feature +) VALUES ( + $1, $2 +) +` + +type InsertInvoiceFeatureParams struct { + InvoiceID int32 + Feature int32 +} + +func (q *Queries) InsertInvoiceFeature(ctx context.Context, arg InsertInvoiceFeatureParams) error { + _, err := q.db.ExecContext(ctx, insertInvoiceFeature, arg.InvoiceID, arg.Feature) + return err +} + +const insertInvoiceHTLC = `-- name: InsertInvoiceHTLC :exec +INSERT INTO invoice_htlcs ( + htlc_id, chan_id, amount_msat, total_mpp_msat, accept_height, accept_time, + expiry_height, state, resolve_time, invoice_id +) VALUES ( + $1, $2, $3, $4, $5, $6, $7, $8, $9, $10 +) +` + +type InsertInvoiceHTLCParams struct { + HtlcID int64 + ChanID string + AmountMsat int64 + TotalMppMsat sql.NullInt64 + AcceptHeight int32 + AcceptTime time.Time + ExpiryHeight int32 + State int16 + ResolveTime sql.NullTime + InvoiceID int32 +} + +func (q *Queries) InsertInvoiceHTLC(ctx context.Context, arg InsertInvoiceHTLCParams) error { + _, err := q.db.ExecContext(ctx, insertInvoiceHTLC, + arg.HtlcID, + arg.ChanID, + arg.AmountMsat, + arg.TotalMppMsat, + arg.AcceptHeight, + arg.AcceptTime, + arg.ExpiryHeight, + arg.State, + arg.ResolveTime, + arg.InvoiceID, + ) + return err +} + +const insertInvoiceHTLCCustomRecord = `-- name: InsertInvoiceHTLCCustomRecord :exec +INSERT INTO invoice_htlc_custom_records ( + key, value, htlc_id +) VALUES ( + $1, $2, $3 +) +` + +type InsertInvoiceHTLCCustomRecordParams struct { + Key int64 + Value []byte + HtlcID int64 +} + +func (q *Queries) InsertInvoiceHTLCCustomRecord(ctx context.Context, arg InsertInvoiceHTLCCustomRecordParams) error { + _, err := q.db.ExecContext(ctx, insertInvoiceHTLCCustomRecord, arg.Key, arg.Value, arg.HtlcID) + return err +} + +const insertInvoicePayment = `-- name: InsertInvoicePayment :one +INSERT INTO invoice_payments ( + invoice_id, amount_paid_msat, settled_at +) VALUES ( + $1, $2, $3 +) RETURNING id +` + +type InsertInvoicePaymentParams struct { + InvoiceID int32 + AmountPaidMsat int64 + SettledAt time.Time +} + +func (q *Queries) InsertInvoicePayment(ctx context.Context, arg InsertInvoicePaymentParams) (int32, error) { + row := q.db.QueryRowContext(ctx, insertInvoicePayment, arg.InvoiceID, arg.AmountPaidMsat, arg.SettledAt) + var id int32 + err := row.Scan(&id) + return id, err +} + +const updateInvoice = `-- name: UpdateInvoice :exec +UPDATE invoices +SET preimage=$2, state=$3, amount_paid_msat=$4 +WHERE id=$1 +` + +type UpdateInvoiceParams struct { + ID int32 + Preimage []byte + State int16 + AmountPaidMsat int64 +} + +func (q *Queries) UpdateInvoice(ctx context.Context, arg UpdateInvoiceParams) error { + _, err := q.db.ExecContext(ctx, updateInvoice, + arg.ID, + arg.Preimage, + arg.State, + arg.AmountPaidMsat, + ) + return err +} + +const updateInvoiceHTLC = `-- name: UpdateInvoiceHTLC :exec +UPDATE invoice_htlcs +SET state=$2, resolve_time=$3 +WHERE id = $1 +` + +type UpdateInvoiceHTLCParams struct { + ID int32 + State int16 + ResolveTime sql.NullTime +} + +func (q *Queries) UpdateInvoiceHTLC(ctx context.Context, arg UpdateInvoiceHTLCParams) error { + _, err := q.db.ExecContext(ctx, updateInvoiceHTLC, arg.ID, arg.State, arg.ResolveTime) + return err +} + +const updateInvoiceHTLCs = `-- name: UpdateInvoiceHTLCs :exec +UPDATE invoice_htlcs +SET state=$2, resolve_time=$3 +WHERE invoice_id = $1 AND resolve_time IS NULL +` + +type UpdateInvoiceHTLCsParams struct { + InvoiceID int32 + State int16 + ResolveTime sql.NullTime +} + +func (q *Queries) UpdateInvoiceHTLCs(ctx context.Context, arg UpdateInvoiceHTLCsParams) error { + _, err := q.db.ExecContext(ctx, updateInvoiceHTLCs, arg.InvoiceID, arg.State, arg.ResolveTime) + return err +} diff --git a/sqldb/sqlc/models.go b/sqldb/sqlc/models.go new file mode 100644 index 000000000..b0ef3c857 --- /dev/null +++ b/sqldb/sqlc/models.go @@ -0,0 +1,93 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.18.0 + +package sqlc + +import ( + "database/sql" + "time" +) + +type AmpInvoiceHtlc struct { + SetID []byte + HtlcID int64 + InvoiceID int32 + RootShare []byte + ChildIndex int64 + Hash []byte + Preimage []byte +} + +type AmpInvoicePayment struct { + SetID []byte + State int16 + CreatedAt time.Time + SettledIndex sql.NullInt32 + InvoiceID int32 +} + +type Invoice struct { + ID int32 + Hash []byte + Preimage []byte + Memo sql.NullString + AmountMsat int64 + CltvDelta sql.NullInt32 + Expiry int32 + PaymentAddr []byte + PaymentRequest sql.NullString + State int16 + AmountPaidMsat int64 + IsAmp bool + IsHodl bool + IsKeysend bool + CreatedAt time.Time +} + +type InvoiceEvent struct { + ID int32 + CreatedAt time.Time + InvoiceID int32 + HtlcID sql.NullInt64 + SetID []byte + EventType int32 + EventMetadata []byte +} + +type InvoiceEventType struct { + ID int32 + Description string +} + +type InvoiceFeature struct { + Feature int32 + InvoiceID int32 +} + +type InvoiceHtlc struct { + ID int32 + HtlcID int64 + ChanID string + AmountMsat int64 + TotalMppMsat sql.NullInt64 + AcceptHeight int32 + AcceptTime time.Time + ExpiryHeight int32 + State int16 + ResolveTime sql.NullTime + InvoiceID int32 +} + +type InvoiceHtlcCustomRecord struct { + Key int64 + Value []byte + HtlcID int64 +} + +type InvoicePayment struct { + ID int32 + SettledAt time.Time + AmountPaidMsat int64 + InvoiceID int32 +} diff --git a/sqldb/sqlc/querier.go b/sqldb/sqlc/querier.go new file mode 100644 index 000000000..1e766ac63 --- /dev/null +++ b/sqldb/sqlc/querier.go @@ -0,0 +1,51 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.18.0 + +package sqlc + +import ( + "context" +) + +type Querier interface { + DeleteAMPHTLCCustomRecords(ctx context.Context, invoiceID int32) error + DeleteAMPHTLCs(ctx context.Context, invoiceID int32) error + DeleteAMPInvoiceHTLC(ctx context.Context, setID []byte) error + DeleteInvoice(ctx context.Context, arg DeleteInvoiceParams) error + DeleteInvoiceEvents(ctx context.Context, invoiceID int32) error + DeleteInvoiceFeatures(ctx context.Context, invoiceID int32) error + DeleteInvoiceHTLC(ctx context.Context, htlcID int64) error + DeleteInvoiceHTLCCustomRecords(ctx context.Context, invoiceID int32) error + DeleteInvoiceHTLCs(ctx context.Context, invoiceID int32) error + FilterInvoicePayments(ctx context.Context, arg FilterInvoicePaymentsParams) ([]FilterInvoicePaymentsRow, error) + FilterInvoices(ctx context.Context, arg FilterInvoicesParams) ([]Invoice, error) + GetAMPInvoiceHTLCsByInvoiceID(ctx context.Context, invoiceID int32) ([]AmpInvoiceHtlc, error) + GetAMPInvoiceHTLCsBySetID(ctx context.Context, setID []byte) ([]AmpInvoiceHtlc, error) + // This method may return more than one invoice if filter using multiple fields + // from different invoices. It is the caller's responsibility to ensure that + // we bubble up an error in those cases. + GetInvoice(ctx context.Context, arg GetInvoiceParams) ([]Invoice, error) + GetInvoiceFeatures(ctx context.Context, invoiceID int32) ([]InvoiceFeature, error) + GetInvoiceHTLCCustomRecords(ctx context.Context, invoiceID int32) ([]GetInvoiceHTLCCustomRecordsRow, error) + GetInvoiceHTLCs(ctx context.Context, invoiceID int32) ([]InvoiceHtlc, error) + GetInvoicePayments(ctx context.Context, invoiceID int32) ([]InvoicePayment, error) + GetSetIDHTLCsCustomRecords(ctx context.Context, setID []byte) ([]GetSetIDHTLCsCustomRecordsRow, error) + InsertAMPInvoiceHTLC(ctx context.Context, arg InsertAMPInvoiceHTLCParams) error + InsertAMPInvoicePayment(ctx context.Context, arg InsertAMPInvoicePaymentParams) error + InsertInvoice(ctx context.Context, arg InsertInvoiceParams) (int32, error) + InsertInvoiceEvent(ctx context.Context, arg InsertInvoiceEventParams) error + InsertInvoiceFeature(ctx context.Context, arg InsertInvoiceFeatureParams) error + InsertInvoiceHTLC(ctx context.Context, arg InsertInvoiceHTLCParams) error + InsertInvoiceHTLCCustomRecord(ctx context.Context, arg InsertInvoiceHTLCCustomRecordParams) error + InsertInvoicePayment(ctx context.Context, arg InsertInvoicePaymentParams) (int32, error) + SelectAMPInvoicePayments(ctx context.Context, arg SelectAMPInvoicePaymentsParams) ([]SelectAMPInvoicePaymentsRow, error) + SelectInvoiceEvents(ctx context.Context, arg SelectInvoiceEventsParams) ([]InvoiceEvent, error) + UpdateAMPInvoiceHTLC(ctx context.Context, arg UpdateAMPInvoiceHTLCParams) error + UpdateAMPPayment(ctx context.Context, arg UpdateAMPPaymentParams) error + UpdateInvoice(ctx context.Context, arg UpdateInvoiceParams) error + UpdateInvoiceHTLC(ctx context.Context, arg UpdateInvoiceHTLCParams) error + UpdateInvoiceHTLCs(ctx context.Context, arg UpdateInvoiceHTLCsParams) error +} + +var _ Querier = (*Queries)(nil) From ff1379a63399f5de1142c1ec05d7a6ed6ae4e2a0 Mon Sep 17 00:00:00 2001 From: positiveblue Date: Tue, 30 May 2023 07:41:42 -0700 Subject: [PATCH 09/10] CI: Add sqlc code generation check --- .github/workflows/main.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 43ef4b815..1796cad3f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -32,6 +32,29 @@ env: GO_VERSION: 1.20.3 jobs: + ######################## + # SQLC code gen check + ######################## + sqlc-check: + name: Sqlc check + runs-on: ubuntu-latest + steps: + - name: git checkout + uses: actions/checkout@v3 + + - name: setup go ${{ env.GO_VERSION }} + uses: ./.github/actions/setup-go + with: + go-version: '${{ env.GO_VERSION }}' + + - name: docker image cache + uses: satackey/action-docker-layer-caching@v0.0.11 + # Ignore the failure of a step and avoid terminating the job. + continue-on-error: true + + - name: Generate sql models + run: make sqlc-check + ######################## # RPC and mobile compilation check ######################## From 8fcb404161503e9012f003e5f5e2250863e10cbe Mon Sep 17 00:00:00 2001 From: positiveblue Date: Thu, 22 Jun 2023 15:28:41 -0700 Subject: [PATCH 10/10] docs: add release note for 7354 --- docs/release-notes/release-notes-0.17.0.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/release-notes/release-notes-0.17.0.md b/docs/release-notes/release-notes-0.17.0.md index 290a9c5f9..cc1cd67cd 100644 --- a/docs/release-notes/release-notes-0.17.0.md +++ b/docs/release-notes/release-notes-0.17.0.md @@ -6,6 +6,9 @@ implementation](https://github.com/lightningnetwork/lnd/pull/7377) logic in different update types. +* Add [invoice SQL schema and + queries](https://github.com/lightningnetwork/lnd/pull/7354) + ## Watchtowers * Let the task pipeline [only carry