loopdb: persist deposit address ownership

Associate every deposit with the static address parameters that created
it. This lets restored deposits recover the correct script and signing
keys instead of assuming the legacy root address.
This commit is contained in:
Slyghtning 2026-07-10 11:58:03 +02:00
parent 1baf02e210
commit 29f5ce73ce
No known key found for this signature in database
GPG key ID: F82D456EA023C9BF
15 changed files with 498 additions and 43 deletions

View file

@ -0,0 +1 @@
ALTER TABLE deposits DROP COLUMN static_address_id;

View file

@ -0,0 +1,8 @@
ALTER TABLE deposits ADD static_address_id INT REFERENCES static_addresses(id);
UPDATE deposits
SET static_address_id = (
SELECT id FROM static_addresses ORDER BY id ASC LIMIT 1
)
WHERE static_address_id IS NULL
AND EXISTS (SELECT 1 FROM static_addresses);

View file

@ -20,6 +20,7 @@ type Deposit struct {
ExpirySweepTxid []byte
FinalizedWithdrawalTx sql.NullString
SwapHash []byte
StaticAddressID sql.NullInt32
}
type DepositUpdate struct {

View file

@ -10,7 +10,7 @@ import (
)
type Querier interface {
AllDeposits(ctx context.Context) ([]Deposit, error)
AllDeposits(ctx context.Context) ([]AllDepositsRow, error)
AllStaticAddresses(ctx context.Context) ([]StaticAddress, error)
CancelBatch(ctx context.Context, id int32) error
CreateDeposit(ctx context.Context, arg CreateDepositParams) error
@ -18,19 +18,20 @@ type Querier interface {
CreateStaticAddress(ctx context.Context, arg CreateStaticAddressParams) error
CreateWithdrawal(ctx context.Context, arg CreateWithdrawalParams) error
CreateWithdrawalDeposit(ctx context.Context, arg CreateWithdrawalDepositParams) error
DepositForOutpoint(ctx context.Context, arg DepositForOutpointParams) (Deposit, error)
DepositForOutpoint(ctx context.Context, arg DepositForOutpointParams) (DepositForOutpointRow, error)
DepositIDsForSwapHash(ctx context.Context, swapHash []byte) ([][]byte, error)
DepositsForSwapHash(ctx context.Context, swapHash []byte) ([]DepositsForSwapHashRow, error)
FetchLiquidityParams(ctx context.Context) ([]byte, error)
GetAllWithdrawals(ctx context.Context) ([]Withdrawal, error)
GetBatchSweeps(ctx context.Context, batchID int32) ([]Sweep, error)
GetBatchSweptAmount(ctx context.Context, batchID int32) (int64, error)
GetDeposit(ctx context.Context, depositID []byte) (Deposit, error)
GetDeposit(ctx context.Context, depositID []byte) (GetDepositRow, error)
GetInstantOutSwap(ctx context.Context, swapHash []byte) (GetInstantOutSwapRow, error)
GetInstantOutSwapUpdates(ctx context.Context, swapHash []byte) ([]InstantoutUpdate, error)
GetInstantOutSwaps(ctx context.Context) ([]GetInstantOutSwapsRow, error)
GetLastUpdateID(ctx context.Context, swapHash []byte) (int32, error)
GetLatestDepositUpdate(ctx context.Context, depositID []byte) (DepositUpdate, error)
GetLegacyAddress(ctx context.Context) (StaticAddress, error)
GetLoopInSwap(ctx context.Context, swapHash []byte) (GetLoopInSwapRow, error)
GetLoopInSwapUpdates(ctx context.Context, swapHash []byte) ([]StaticAddressSwapUpdate, error)
GetLoopInSwaps(ctx context.Context) ([]GetLoopInSwapsRow, error)
@ -42,6 +43,7 @@ type Querier interface {
GetReservationUpdates(ctx context.Context, reservationID []byte) ([]ReservationUpdate, error)
GetReservations(ctx context.Context) ([]Reservation, error)
GetStaticAddress(ctx context.Context, pkscript []byte) (StaticAddress, error)
GetStaticAddressID(ctx context.Context, pkscript []byte) (int32, error)
GetStaticAddressLoopInSwap(ctx context.Context, swapHash []byte) (GetStaticAddressLoopInSwapRow, error)
GetStaticAddressLoopInSwapsByStates(ctx context.Context, dollar_1 sql.NullString) ([]GetStaticAddressLoopInSwapsByStatesRow, error)
GetSwapUpdates(ctx context.Context, swapHash []byte) ([]SwapUpdate, error)
@ -68,6 +70,7 @@ type Querier interface {
OverrideSelectedSwapAmount(ctx context.Context, arg OverrideSelectedSwapAmountParams) error
OverrideSwapCosts(ctx context.Context, arg OverrideSwapCostsParams) error
RecordStaticAddressRiskDecision(ctx context.Context, arg RecordStaticAddressRiskDecisionParams) error
SetAllNullDepositsStaticAddressID(ctx context.Context, staticAddressID sql.NullInt32) error
SwapHashForDepositID(ctx context.Context, depositID []byte) ([]byte, error)
UpdateBatch(ctx context.Context, arg UpdateBatchParams) error
UpdateDeposit(ctx context.Context, arg UpdateDepositParams) error

View file

@ -7,7 +7,8 @@ INSERT INTO deposits (
confirmation_height,
timeout_sweep_pk_script,
expiry_sweep_txid,
finalized_withdrawal_tx
finalized_withdrawal_tx,
static_address_id
) VALUES (
$1,
$2,
@ -16,7 +17,8 @@ INSERT INTO deposits (
$5,
$6,
$7,
$8
$8,
$9
);
-- name: UpdateDeposit :exec
@ -43,17 +45,35 @@ INSERT INTO deposit_updates (
-- name: GetDeposit :one
SELECT
*
d.*,
sa.client_pubkey client_pubkey,
sa.server_pubkey server_pubkey,
sa.expiry expiry,
sa.client_key_family client_key_family,
sa.client_key_index client_key_index,
sa.pkscript pkscript,
sa.protocol_version protocol_version,
sa.initiation_height initiation_height
FROM
deposits
deposits d
LEFT JOIN static_addresses sa ON sa.id = d.static_address_id
WHERE
deposit_id = $1;
-- name: DepositForOutpoint :one
SELECT
*
d.*,
sa.client_pubkey client_pubkey,
sa.server_pubkey server_pubkey,
sa.expiry expiry,
sa.client_key_family client_key_family,
sa.client_key_index client_key_index,
sa.pkscript pkscript,
sa.protocol_version protocol_version,
sa.initiation_height initiation_height
FROM
deposits
deposits d
LEFT JOIN static_addresses sa ON sa.id = d.static_address_id
WHERE
tx_hash = $1
AND
@ -61,11 +81,20 @@ AND
-- name: AllDeposits :many
SELECT
*
d.*,
sa.client_pubkey client_pubkey,
sa.server_pubkey server_pubkey,
sa.expiry expiry,
sa.client_key_family client_key_family,
sa.client_key_index client_key_index,
sa.pkscript pkscript,
sa.protocol_version protocol_version,
sa.initiation_height initiation_height
FROM
deposits
deposits d
LEFT JOIN static_addresses sa ON sa.id = d.static_address_id
ORDER BY
id ASC;
d.id ASC;
-- name: GetLatestDepositUpdate :one
SELECT
@ -76,4 +105,9 @@ WHERE
deposit_id = $1
ORDER BY
update_timestamp DESC
LIMIT 1;
LIMIT 1;
-- name: SetAllNullDepositsStaticAddressID :exec
UPDATE deposits
SET static_address_id = $1
WHERE static_address_id IS NULL;

View file

@ -1,10 +1,15 @@
-- name: AllStaticAddresses :many
SELECT * FROM static_addresses;
SELECT * FROM static_addresses
ORDER BY id ASC;
-- name: GetStaticAddress :one
SELECT * FROM static_addresses
WHERE pkscript=$1;
-- name: GetStaticAddressID :one
SELECT id FROM static_addresses
WHERE pkscript=$1;
-- name: CreateStaticAddress :exec
INSERT INTO static_addresses (
client_pubkey,
@ -24,4 +29,9 @@ INSERT INTO static_addresses (
$6,
$7,
$8
);
);
-- name: GetLegacyAddress :one
SELECT * FROM static_addresses
ORDER BY id ASC
LIMIT 1;

View file

@ -13,22 +13,53 @@ import (
const allDeposits = `-- name: AllDeposits :many
SELECT
id, deposit_id, tx_hash, out_index, amount, confirmation_height, timeout_sweep_pk_script, expiry_sweep_txid, finalized_withdrawal_tx, swap_hash
d.id, d.deposit_id, d.tx_hash, d.out_index, d.amount, d.confirmation_height, d.timeout_sweep_pk_script, d.expiry_sweep_txid, d.finalized_withdrawal_tx, d.swap_hash, d.static_address_id,
sa.client_pubkey client_pubkey,
sa.server_pubkey server_pubkey,
sa.expiry expiry,
sa.client_key_family client_key_family,
sa.client_key_index client_key_index,
sa.pkscript pkscript,
sa.protocol_version protocol_version,
sa.initiation_height initiation_height
FROM
deposits
deposits d
LEFT JOIN static_addresses sa ON sa.id = d.static_address_id
ORDER BY
id ASC
d.id ASC
`
func (q *Queries) AllDeposits(ctx context.Context) ([]Deposit, error) {
type AllDepositsRow struct {
ID int32
DepositID []byte
TxHash []byte
OutIndex int32
Amount int64
ConfirmationHeight int64
TimeoutSweepPkScript []byte
ExpirySweepTxid []byte
FinalizedWithdrawalTx sql.NullString
SwapHash []byte
StaticAddressID sql.NullInt32
ClientPubkey []byte
ServerPubkey []byte
Expiry sql.NullInt32
ClientKeyFamily sql.NullInt32
ClientKeyIndex sql.NullInt32
Pkscript []byte
ProtocolVersion sql.NullInt32
InitiationHeight sql.NullInt32
}
func (q *Queries) AllDeposits(ctx context.Context) ([]AllDepositsRow, error) {
rows, err := q.db.QueryContext(ctx, allDeposits)
if err != nil {
return nil, err
}
defer rows.Close()
var items []Deposit
var items []AllDepositsRow
for rows.Next() {
var i Deposit
var i AllDepositsRow
if err := rows.Scan(
&i.ID,
&i.DepositID,
@ -40,6 +71,15 @@ func (q *Queries) AllDeposits(ctx context.Context) ([]Deposit, error) {
&i.ExpirySweepTxid,
&i.FinalizedWithdrawalTx,
&i.SwapHash,
&i.StaticAddressID,
&i.ClientPubkey,
&i.ServerPubkey,
&i.Expiry,
&i.ClientKeyFamily,
&i.ClientKeyIndex,
&i.Pkscript,
&i.ProtocolVersion,
&i.InitiationHeight,
); err != nil {
return nil, err
}
@ -63,7 +103,8 @@ INSERT INTO deposits (
confirmation_height,
timeout_sweep_pk_script,
expiry_sweep_txid,
finalized_withdrawal_tx
finalized_withdrawal_tx,
static_address_id
) VALUES (
$1,
$2,
@ -72,7 +113,8 @@ INSERT INTO deposits (
$5,
$6,
$7,
$8
$8,
$9
)
`
@ -85,6 +127,7 @@ type CreateDepositParams struct {
TimeoutSweepPkScript []byte
ExpirySweepTxid []byte
FinalizedWithdrawalTx sql.NullString
StaticAddressID sql.NullInt32
}
func (q *Queries) CreateDeposit(ctx context.Context, arg CreateDepositParams) error {
@ -97,15 +140,25 @@ func (q *Queries) CreateDeposit(ctx context.Context, arg CreateDepositParams) er
arg.TimeoutSweepPkScript,
arg.ExpirySweepTxid,
arg.FinalizedWithdrawalTx,
arg.StaticAddressID,
)
return err
}
const depositForOutpoint = `-- name: DepositForOutpoint :one
SELECT
id, deposit_id, tx_hash, out_index, amount, confirmation_height, timeout_sweep_pk_script, expiry_sweep_txid, finalized_withdrawal_tx, swap_hash
d.id, d.deposit_id, d.tx_hash, d.out_index, d.amount, d.confirmation_height, d.timeout_sweep_pk_script, d.expiry_sweep_txid, d.finalized_withdrawal_tx, d.swap_hash, d.static_address_id,
sa.client_pubkey client_pubkey,
sa.server_pubkey server_pubkey,
sa.expiry expiry,
sa.client_key_family client_key_family,
sa.client_key_index client_key_index,
sa.pkscript pkscript,
sa.protocol_version protocol_version,
sa.initiation_height initiation_height
FROM
deposits
deposits d
LEFT JOIN static_addresses sa ON sa.id = d.static_address_id
WHERE
tx_hash = $1
AND
@ -117,9 +170,31 @@ type DepositForOutpointParams struct {
OutIndex int32
}
func (q *Queries) DepositForOutpoint(ctx context.Context, arg DepositForOutpointParams) (Deposit, error) {
type DepositForOutpointRow struct {
ID int32
DepositID []byte
TxHash []byte
OutIndex int32
Amount int64
ConfirmationHeight int64
TimeoutSweepPkScript []byte
ExpirySweepTxid []byte
FinalizedWithdrawalTx sql.NullString
SwapHash []byte
StaticAddressID sql.NullInt32
ClientPubkey []byte
ServerPubkey []byte
Expiry sql.NullInt32
ClientKeyFamily sql.NullInt32
ClientKeyIndex sql.NullInt32
Pkscript []byte
ProtocolVersion sql.NullInt32
InitiationHeight sql.NullInt32
}
func (q *Queries) DepositForOutpoint(ctx context.Context, arg DepositForOutpointParams) (DepositForOutpointRow, error) {
row := q.db.QueryRowContext(ctx, depositForOutpoint, arg.TxHash, arg.OutIndex)
var i Deposit
var i DepositForOutpointRow
err := row.Scan(
&i.ID,
&i.DepositID,
@ -131,22 +206,62 @@ func (q *Queries) DepositForOutpoint(ctx context.Context, arg DepositForOutpoint
&i.ExpirySweepTxid,
&i.FinalizedWithdrawalTx,
&i.SwapHash,
&i.StaticAddressID,
&i.ClientPubkey,
&i.ServerPubkey,
&i.Expiry,
&i.ClientKeyFamily,
&i.ClientKeyIndex,
&i.Pkscript,
&i.ProtocolVersion,
&i.InitiationHeight,
)
return i, err
}
const getDeposit = `-- name: GetDeposit :one
SELECT
id, deposit_id, tx_hash, out_index, amount, confirmation_height, timeout_sweep_pk_script, expiry_sweep_txid, finalized_withdrawal_tx, swap_hash
d.id, d.deposit_id, d.tx_hash, d.out_index, d.amount, d.confirmation_height, d.timeout_sweep_pk_script, d.expiry_sweep_txid, d.finalized_withdrawal_tx, d.swap_hash, d.static_address_id,
sa.client_pubkey client_pubkey,
sa.server_pubkey server_pubkey,
sa.expiry expiry,
sa.client_key_family client_key_family,
sa.client_key_index client_key_index,
sa.pkscript pkscript,
sa.protocol_version protocol_version,
sa.initiation_height initiation_height
FROM
deposits
deposits d
LEFT JOIN static_addresses sa ON sa.id = d.static_address_id
WHERE
deposit_id = $1
`
func (q *Queries) GetDeposit(ctx context.Context, depositID []byte) (Deposit, error) {
type GetDepositRow struct {
ID int32
DepositID []byte
TxHash []byte
OutIndex int32
Amount int64
ConfirmationHeight int64
TimeoutSweepPkScript []byte
ExpirySweepTxid []byte
FinalizedWithdrawalTx sql.NullString
SwapHash []byte
StaticAddressID sql.NullInt32
ClientPubkey []byte
ServerPubkey []byte
Expiry sql.NullInt32
ClientKeyFamily sql.NullInt32
ClientKeyIndex sql.NullInt32
Pkscript []byte
ProtocolVersion sql.NullInt32
InitiationHeight sql.NullInt32
}
func (q *Queries) GetDeposit(ctx context.Context, depositID []byte) (GetDepositRow, error) {
row := q.db.QueryRowContext(ctx, getDeposit, depositID)
var i Deposit
var i GetDepositRow
err := row.Scan(
&i.ID,
&i.DepositID,
@ -158,6 +273,15 @@ func (q *Queries) GetDeposit(ctx context.Context, depositID []byte) (Deposit, er
&i.ExpirySweepTxid,
&i.FinalizedWithdrawalTx,
&i.SwapHash,
&i.StaticAddressID,
&i.ClientPubkey,
&i.ServerPubkey,
&i.Expiry,
&i.ClientKeyFamily,
&i.ClientKeyIndex,
&i.Pkscript,
&i.ProtocolVersion,
&i.InitiationHeight,
)
return i, err
}
@ -209,6 +333,17 @@ func (q *Queries) InsertDepositUpdate(ctx context.Context, arg InsertDepositUpda
return err
}
const setAllNullDepositsStaticAddressID = `-- name: SetAllNullDepositsStaticAddressID :exec
UPDATE deposits
SET static_address_id = $1
WHERE static_address_id IS NULL
`
func (q *Queries) SetAllNullDepositsStaticAddressID(ctx context.Context, staticAddressID sql.NullInt32) error {
_, err := q.db.ExecContext(ctx, setAllNullDepositsStaticAddressID, staticAddressID)
return err
}
const updateDeposit = `-- name: UpdateDeposit :exec
UPDATE deposits
SET

View file

@ -45,7 +45,7 @@ func (q *Queries) DepositIDsForSwapHash(ctx context.Context, swapHash []byte) ([
const depositsForSwapHash = `-- name: DepositsForSwapHash :many
SELECT
d.id, d.deposit_id, d.tx_hash, d.out_index, d.amount, d.confirmation_height, d.timeout_sweep_pk_script, d.expiry_sweep_txid, d.finalized_withdrawal_tx, d.swap_hash,
d.id, d.deposit_id, d.tx_hash, d.out_index, d.amount, d.confirmation_height, d.timeout_sweep_pk_script, d.expiry_sweep_txid, d.finalized_withdrawal_tx, d.swap_hash, d.static_address_id,
u.update_state,
u.update_timestamp
FROM
@ -73,6 +73,7 @@ type DepositsForSwapHashRow struct {
ExpirySweepTxid []byte
FinalizedWithdrawalTx sql.NullString
SwapHash []byte
StaticAddressID sql.NullInt32
UpdateState sql.NullString
UpdateTimestamp sql.NullTime
}
@ -97,6 +98,7 @@ func (q *Queries) DepositsForSwapHash(ctx context.Context, swapHash []byte) ([]D
&i.ExpirySweepTxid,
&i.FinalizedWithdrawalTx,
&i.SwapHash,
&i.StaticAddressID,
&i.UpdateState,
&i.UpdateTimestamp,
); err != nil {

View file

@ -11,6 +11,7 @@ import (
const allStaticAddresses = `-- name: AllStaticAddresses :many
SELECT id, client_pubkey, server_pubkey, expiry, client_key_family, client_key_index, pkscript, protocol_version, initiation_height FROM static_addresses
ORDER BY id ASC
`
func (q *Queries) AllStaticAddresses(ctx context.Context) ([]StaticAddress, error) {
@ -93,6 +94,29 @@ func (q *Queries) CreateStaticAddress(ctx context.Context, arg CreateStaticAddre
return err
}
const getLegacyAddress = `-- name: GetLegacyAddress :one
SELECT id, client_pubkey, server_pubkey, expiry, client_key_family, client_key_index, pkscript, protocol_version, initiation_height FROM static_addresses
ORDER BY id ASC
LIMIT 1
`
func (q *Queries) GetLegacyAddress(ctx context.Context) (StaticAddress, error) {
row := q.db.QueryRowContext(ctx, getLegacyAddress)
var i StaticAddress
err := row.Scan(
&i.ID,
&i.ClientPubkey,
&i.ServerPubkey,
&i.Expiry,
&i.ClientKeyFamily,
&i.ClientKeyIndex,
&i.Pkscript,
&i.ProtocolVersion,
&i.InitiationHeight,
)
return i, err
}
const getStaticAddress = `-- name: GetStaticAddress :one
SELECT id, client_pubkey, server_pubkey, expiry, client_key_family, client_key_index, pkscript, protocol_version, initiation_height FROM static_addresses
WHERE pkscript=$1
@ -114,3 +138,15 @@ func (q *Queries) GetStaticAddress(ctx context.Context, pkscript []byte) (Static
)
return i, err
}
const getStaticAddressID = `-- name: GetStaticAddressID :one
SELECT id FROM static_addresses
WHERE pkscript=$1
`
func (q *Queries) GetStaticAddressID(ctx context.Context, pkscript []byte) (int32, error) {
row := q.db.QueryRowContext(ctx, getStaticAddressID, pkscript)
var id int32
err := row.Scan(&id)
return id, err
}