staticaddr: interfaces

Slyghtning 2 months ago
parent 411c226bbf
commit e66291ef68
No known key found for this signature in database
GPG Key ID: F82D456EA023C9BF

@ -1,39 +1,38 @@
package staticaddr
package address
import (
"context"
"fmt"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/lightninglabs/loop/staticaddr"
"github.com/lightningnetwork/lnd/keychain"
)
var (
ErrAddressAlreadyExists = fmt.Errorf("address already exists")
ErrAddressNotFound = fmt.Errorf("address not found")
)
// AddressStore is the database interface that is used to store and retrieve
// Store is the database interface that is used to store and retrieve
// static addresses.
type AddressStore interface {
type Store interface {
// CreateStaticAddress inserts a new static address with its parameters
// into the store.
CreateStaticAddress(ctx context.Context,
addrParams *AddressParameters) error
CreateStaticAddress(ctx context.Context, addrParams *Parameters) error
// GetStaticAddress fetches static address parameters for a given
// address ID.
GetStaticAddress(ctx context.Context,
pkScript []byte) (*AddressParameters, error)
GetStaticAddress(ctx context.Context, pkScript []byte) (*Parameters,
error)
// GetAllStaticAddresses retrieves all static addresses from the store.
GetAllStaticAddresses(ctx context.Context) (
[]*AddressParameters, error)
GetAllStaticAddresses(ctx context.Context) ([]*Parameters,
error)
}
// AddressParameters holds all the necessary information for the 2-of-2 multisig
// Parameters holds all the necessary information for the 2-of-2 multisig
// address.
type AddressParameters struct {
type Parameters struct {
// ClientPubkey is the client's pubkey for the static address. It is
// used for the 2-of-2 funding output as well as for the client's
// timeout path.
@ -54,5 +53,5 @@ type AddressParameters struct {
KeyLocator keychain.KeyLocator
// ProtocolVersion is the protocol version of the static address.
ProtocolVersion AddressProtocolVersion
ProtocolVersion staticaddr.AddressProtocolVersion
}

@ -1,4 +1,4 @@
package staticaddr
package address
import (
"context"
@ -8,6 +8,7 @@ import (
"github.com/jackc/pgx/v4"
"github.com/lightninglabs/loop/loopdb"
"github.com/lightninglabs/loop/loopdb/sqlc"
"github.com/lightninglabs/loop/staticaddr"
"github.com/lightningnetwork/lnd/keychain"
)
@ -63,7 +64,7 @@ func (s *SqlStore) ExecTx(ctx context.Context, txOptions loopdb.TxOptions,
// CreateStaticAddress creates a static address record in the database.
func (s *SqlStore) CreateStaticAddress(ctx context.Context,
addrParams *AddressParameters) error {
addrParams *Parameters) error {
createArgs := sqlc.CreateStaticAddressParams{
ClientPubkey: addrParams.ClientPubkey.SerializeCompressed(),
@ -80,7 +81,7 @@ func (s *SqlStore) CreateStaticAddress(ctx context.Context,
// GetStaticAddress retrieves static address parameters for a given pkScript.
func (s *SqlStore) GetStaticAddress(ctx context.Context,
pkScript []byte) (*AddressParameters, error) {
pkScript []byte) (*Parameters, error) {
staticAddress, err := s.baseDB.Queries.GetStaticAddress(ctx, pkScript)
if err != nil {
@ -91,15 +92,15 @@ func (s *SqlStore) GetStaticAddress(ctx context.Context,
}
// GetAllStaticAddresses returns all address known to the server.
func (s *SqlStore) GetAllStaticAddresses(ctx context.Context) (
[]*AddressParameters, error) {
func (s *SqlStore) GetAllStaticAddresses(ctx context.Context) ([]*Parameters,
error) {
staticAddresses, err := s.baseDB.Queries.AllStaticAddresses(ctx)
if err != nil {
return nil, err
}
var result []*AddressParameters
var result []*Parameters
for _, address := range staticAddresses {
res, err := s.toAddressParameters(address)
if err != nil {
@ -120,7 +121,7 @@ func (s *SqlStore) Close() {
// toAddressParameters transforms a database representation of a static address
// to an AddressParameters struct.
func (s *SqlStore) toAddressParameters(row sqlc.StaticAddress) (
*AddressParameters, error) {
*Parameters, error) {
clientPubkey, err := btcec.ParsePubKey(row.ClientPubkey)
if err != nil {
@ -132,7 +133,7 @@ func (s *SqlStore) toAddressParameters(row sqlc.StaticAddress) (
return nil, err
}
return &AddressParameters{
return &Parameters{
ClientPubkey: clientPubkey,
ServerPubkey: serverPubkey,
PkScript: row.Pkscript,
@ -141,6 +142,6 @@ func (s *SqlStore) toAddressParameters(row sqlc.StaticAddress) (
Family: keychain.KeyFamily(row.ClientKeyFamily),
Index: uint32(row.ClientKeyIndex),
},
ProtocolVersion: AddressProtocolVersion(row.ProtocolVersion),
ProtocolVersion: staticaddr.AddressProtocolVersion(row.ProtocolVersion),
}, nil
}

@ -0,0 +1,44 @@
package deposit
import (
"context"
"github.com/lightninglabs/loop/staticaddr/address"
"github.com/lightninglabs/loop/staticaddr/script"
"github.com/lightningnetwork/lnd/lnwallet"
)
const (
IdLength = 32
)
// Store is the database interface that is used to store and retrieve
// static address deposits.
type Store interface {
// CreateDeposit inserts a new deposit into the store.
CreateDeposit(ctx context.Context, deposit *Deposit) error
// UpdateDeposit updates the deposit in the database.
UpdateDeposit(ctx context.Context, deposit *Deposit) error
// GetDeposit retrieves a deposit with depositID from the database.
GetDeposit(ctx context.Context, depositID ID) (*Deposit, error)
// AllDeposits retrieves all deposits from the store.
AllDeposits(ctx context.Context) ([]*Deposit, error)
}
// AddressManager handles fetching of address parameters.
type AddressManager interface {
// GetStaticAddressParameters returns the static address parameters.
GetStaticAddressParameters(ctx context.Context) (*address.Parameters,
error)
// GetStaticAddress returns the deposit address for the given
// client and server public keys.
GetStaticAddress(ctx context.Context) (*script.StaticAddress, error)
// ListUnspent returns a list of utxos at the static address.
ListUnspent(ctx context.Context, minConfs,
maxConfs int32) ([]*lnwallet.Utxo, error)
}

@ -0,0 +1,213 @@
package deposit
import (
"context"
"database/sql"
"github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/wire"
"github.com/lightninglabs/loop/fsm"
"github.com/lightninglabs/loop/loopdb"
"github.com/lightninglabs/loop/loopdb/sqlc"
"github.com/lightningnetwork/lnd/clock"
)
// SqlStore is the backing store for static addresses.
type SqlStore struct {
baseDB *loopdb.BaseDB
clock clock.Clock
}
// NewSqlStore constructs a new SQLStore from a BaseDB. The BaseDB is agnostic
// to the underlying driver which can be postgres or sqlite.
func NewSqlStore(db *loopdb.BaseDB) *SqlStore {
return &SqlStore{
baseDB: db,
clock: clock.NewDefaultClock(),
}
}
// CreateDeposit creates a static address record in the database.
func (s *SqlStore) CreateDeposit(ctx context.Context, deposit *Deposit) error {
createArgs := sqlc.CreateDepositParams{
DepositID: deposit.ID[:],
TxHash: deposit.Hash[:],
OutIndex: int32(deposit.Index),
Amount: int64(deposit.Value),
ConfirmationHeight: deposit.ConfirmationHeight,
TimeoutSweepPkScript: deposit.TimeOutSweepPkScript,
}
updateArgs := sqlc.InsertDepositUpdateParams{
DepositID: deposit.ID[:],
UpdateTimestamp: s.clock.Now().UTC(),
UpdateState: string(deposit.State),
}
return s.baseDB.ExecTx(ctx, &loopdb.SqliteTxOptions{},
func(q *sqlc.Queries) error {
err := q.CreateDeposit(ctx, createArgs)
if err != nil {
return err
}
return q.InsertDepositUpdate(ctx, updateArgs)
})
}
// UpdateDeposit updates the deposit in the database.
func (s *SqlStore) UpdateDeposit(ctx context.Context, deposit *Deposit) error {
insertUpdateArgs := sqlc.InsertDepositUpdateParams{
DepositID: deposit.ID[:],
UpdateTimestamp: s.clock.Now().UTC(),
UpdateState: string(deposit.State),
}
var (
txHash = deposit.Hash[:]
outIndex = sql.NullInt32{
Int32: int32(deposit.Index),
Valid: true,
}
confirmationHeight = sql.NullInt64{
Int64: deposit.ConfirmationHeight,
Valid: deposit.ConfirmationHeight != 0,
}
)
updateArgs := sqlc.UpdateDepositParams{
DepositID: deposit.ID[:],
TxHash: txHash,
OutIndex: outIndex.Int32,
ConfirmationHeight: confirmationHeight.Int64,
ExpirySweepTxid: deposit.ExpirySweepTxid[:],
}
return s.baseDB.ExecTx(ctx, &loopdb.SqliteTxOptions{},
func(q *sqlc.Queries) error {
err := q.UpdateDeposit(ctx, updateArgs)
if err != nil {
return err
}
return q.InsertDepositUpdate(ctx, insertUpdateArgs)
})
}
// GetDeposit retrieves the deposit from the database.
func (s *SqlStore) GetDeposit(ctx context.Context, id ID) (*Deposit, error) {
var deposit *Deposit
err := s.baseDB.ExecTx(ctx, loopdb.NewSqlReadOpts(),
func(q *sqlc.Queries) error {
row, err := q.GetDeposit(ctx, id[:])
if err != nil {
return err
}
latestUpdate, err := q.GetLatestDepositUpdate(
ctx, id[:],
)
if err != nil {
return err
}
deposit, err = s.toDeposit(row, latestUpdate)
if err != nil {
return err
}
return nil
})
if err != nil {
return nil, err
}
return deposit, nil
}
// AllDeposits retrieves all known deposits to our static address.
func (s *SqlStore) AllDeposits(ctx context.Context) ([]*Deposit, error) {
var allDeposits []*Deposit
err := s.baseDB.ExecTx(ctx, loopdb.NewSqlReadOpts(),
func(q *sqlc.Queries) error {
var err error
deposits, err := q.AllDeposits(ctx)
if err != nil {
return err
}
for _, deposit := range deposits {
latestUpdate, err := q.GetLatestDepositUpdate(
ctx, deposit.DepositID,
)
if err != nil {
return err
}
d, err := s.toDeposit(deposit, latestUpdate)
if err != nil {
return err
}
allDeposits = append(allDeposits, d)
}
return nil
})
if err != nil {
return nil, err
}
return allDeposits, nil
}
// toDeposit converts an sql deposit to a deposit.
func (s *SqlStore) toDeposit(row sqlc.Deposit,
lastUpdate sqlc.DepositUpdate) (*Deposit, error) {
id := ID{}
err := id.FromByteSlice(row.DepositID)
if err != nil {
return nil, err
}
var txHash *chainhash.Hash
if row.TxHash != nil {
txHash, err = chainhash.NewHash(row.TxHash)
if err != nil {
return nil, err
}
}
var expirySweepTxid chainhash.Hash
if row.ExpirySweepTxid != nil {
hash, err := chainhash.NewHash(row.ExpirySweepTxid)
if err != nil {
return nil, err
}
expirySweepTxid = *hash
}
return &Deposit{
ID: id,
State: fsm.StateType(lastUpdate.UpdateState),
OutPoint: wire.OutPoint{
Hash: *txHash,
Index: uint32(row.OutIndex),
},
Value: btcutil.Amount(row.Amount),
ConfirmationHeight: row.ConfirmationHeight,
TimeOutSweepPkScript: row.TimeoutSweepPkScript,
ExpirySweepTxid: expirySweepTxid,
}, nil
}
// Close closes the database connection.
func (s *SqlStore) Close() {
s.baseDB.DB.Close()
}
Loading…
Cancel
Save