mirror of
https://github.com/lightninglabs/loop.git
synced 2026-08-16 13:00:37 +02:00
staticaddr: expose addresses in deposit listings
Include the owning static address in every deposit RPC response and CLI listing. Users can distinguish deposits created by different receive and change addresses without reconstructing scripts externally. Update generated RPC artifacts and command replay fixtures for the new field.
This commit is contained in:
parent
88039c2125
commit
4bc75d8ec6
17 changed files with 159 additions and 69 deletions
|
|
@ -1108,24 +1108,13 @@ func (s *swapClientServer) GetLoopInQuote(ctx context.Context,
|
|||
"deposits: %w", err)
|
||||
}
|
||||
|
||||
// TODO(hieblmi): add params to deposit for multi-address
|
||||
// support.
|
||||
params, err := s.staticAddressManager.GetStaticAddressParameters(
|
||||
ctx,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to retrieve static "+
|
||||
"address parameters: %w", err)
|
||||
}
|
||||
|
||||
info, err := s.lnd.Client.GetInfo(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to get lnd info: %w",
|
||||
err)
|
||||
}
|
||||
selectedDeposits, err := loopin.SelectDeposits(
|
||||
selectedAmount, deposits, params.Expiry,
|
||||
info.BlockHeight,
|
||||
selectedAmount, deposits, info.BlockHeight,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to select deposits: %w",
|
||||
|
|
@ -2206,7 +2195,10 @@ func (s *swapClientServer) ListStaticAddressDeposits(ctx context.Context,
|
|||
f := func(d *deposit.Deposit) bool {
|
||||
return slices.Contains(outpoints, d.OutPoint.String())
|
||||
}
|
||||
filteredDeposits = filter(allDeposits, f)
|
||||
filteredDeposits, err = s.filterDeposits(allDeposits, f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(outpoints) != len(filteredDeposits) {
|
||||
return nil, fmt.Errorf("not all outpoints found in " +
|
||||
|
|
@ -2222,11 +2214,14 @@ func (s *swapClientServer) ListStaticAddressDeposits(ctx context.Context,
|
|||
|
||||
return d.IsInState(toServerState(req.StateFilter))
|
||||
}
|
||||
filteredDeposits = filter(allDeposits, f)
|
||||
filteredDeposits, err = s.filterDeposits(allDeposits, f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate the blocks until expiry for each deposit.
|
||||
err = s.populateBlocksUntilExpiry(ctx, filteredDeposits)
|
||||
err = s.populateBlocksUntilExpiry(ctx, allDeposits, filteredDeposits)
|
||||
if err != nil {
|
||||
infof("Failed to populate blocks until expiry: %v", err)
|
||||
}
|
||||
|
|
@ -2304,13 +2299,6 @@ func (s *swapClientServer) ListStaticAddressSwaps(ctx context.Context,
|
|||
return nil, err
|
||||
}
|
||||
|
||||
addrParams, err := s.staticAddressManager.GetStaticAddressParameters(
|
||||
ctx,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Fetch all deposits at once and index them by swap hash for a quick
|
||||
// lookup.
|
||||
allDeposits, err := s.depositManager.GetAllDeposits(ctx)
|
||||
|
|
@ -2351,22 +2339,23 @@ func (s *swapClientServer) ListStaticAddressSwaps(ctx context.Context,
|
|||
if ds, ok := depositsBySwap[swp.SwapHash]; ok {
|
||||
protoDeposits = make([]*looprpc.Deposit, 0, len(ds))
|
||||
for _, d := range ds {
|
||||
state := toClientDepositState(d.GetState())
|
||||
confirmationHeight := d.GetConfirmationHeight()
|
||||
if d.AddressParams == nil {
|
||||
return nil, fmt.Errorf("missing static "+
|
||||
"address parameters for deposit %v",
|
||||
d.OutPoint)
|
||||
}
|
||||
blocksUntilExpiry := depositBlocksUntilExpiry(
|
||||
confirmationHeight, addrParams.Expiry,
|
||||
confirmationHeight,
|
||||
d.AddressParams.Expiry,
|
||||
int64(lndInfo.BlockHeight),
|
||||
)
|
||||
|
||||
pd := &looprpc.Deposit{
|
||||
Id: d.ID[:],
|
||||
State: state,
|
||||
Outpoint: d.OutPoint.String(),
|
||||
Value: int64(d.Value),
|
||||
ConfirmationHeight: confirmationHeight,
|
||||
SwapHash: d.SwapHash[:],
|
||||
BlocksUntilExpiry: blocksUntilExpiry,
|
||||
pd, err := s.rpcDeposit(d)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pd.BlocksUntilExpiry = blocksUntilExpiry
|
||||
protoDeposits = append(protoDeposits, pd)
|
||||
}
|
||||
}
|
||||
|
|
@ -2685,11 +2674,14 @@ func (s *swapClientServer) StaticAddressLoopIn(ctx context.Context,
|
|||
}
|
||||
|
||||
// Build a list of used deposits for the response.
|
||||
usedDeposits := filter(
|
||||
usedDeposits, err := s.filterDeposits(
|
||||
loopIn.Deposits, func(d *deposit.Deposit) bool { return true },
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = s.populateBlocksUntilExpiry(ctx, usedDeposits)
|
||||
err = s.populateBlocksUntilExpiry(ctx, loopIn.Deposits, usedDeposits)
|
||||
if err != nil {
|
||||
infof("Failed to populate blocks until expiry: %v", err)
|
||||
}
|
||||
|
|
@ -2731,21 +2723,31 @@ func (s *swapClientServer) StaticAddressLoopIn(ctx context.Context,
|
|||
// Calculate the blocks until expiry for each deposit and return the modified
|
||||
// StaticAddressLoopInResponse.
|
||||
func (s *swapClientServer) populateBlocksUntilExpiry(ctx context.Context,
|
||||
deposits []*looprpc.Deposit) error {
|
||||
sourceDeposits []*deposit.Deposit, deposits []*looprpc.Deposit) error {
|
||||
|
||||
lndInfo, err := s.lnd.Client.GetInfo(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bestBlockHeight := int64(lndInfo.BlockHeight)
|
||||
params, err := s.staticAddressManager.GetStaticAddressParameters(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
expiryByOutpoint := make(map[string]uint32, len(sourceDeposits))
|
||||
for _, d := range sourceDeposits {
|
||||
if d.AddressParams == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
expiryByOutpoint[d.OutPoint.String()] = d.AddressParams.Expiry
|
||||
}
|
||||
|
||||
bestBlockHeight := int64(lndInfo.BlockHeight)
|
||||
for i := range len(deposits) {
|
||||
expiry, ok := expiryByOutpoint[deposits[i].Outpoint]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
deposits[i].BlocksUntilExpiry = depositBlocksUntilExpiry(
|
||||
deposits[i].ConfirmationHeight, params.Expiry,
|
||||
deposits[i].ConfirmationHeight, expiry,
|
||||
bestBlockHeight,
|
||||
)
|
||||
}
|
||||
|
|
@ -2794,35 +2796,65 @@ func (s *swapClientServer) StaticOpenChannel(ctx context.Context,
|
|||
|
||||
type filterFunc func(deposits *deposit.Deposit) bool
|
||||
|
||||
func filter(deposits []*deposit.Deposit, f filterFunc) []*looprpc.Deposit {
|
||||
func (s *swapClientServer) filterDeposits(deposits []*deposit.Deposit,
|
||||
f filterFunc) ([]*looprpc.Deposit, error) {
|
||||
|
||||
var clientDeposits []*looprpc.Deposit
|
||||
for _, d := range deposits {
|
||||
if !f(d) {
|
||||
continue
|
||||
}
|
||||
|
||||
swapHash := make([]byte, 0, len(lntypes.Hash{}))
|
||||
if d.SwapHash != nil {
|
||||
swapHash = d.SwapHash[:]
|
||||
}
|
||||
|
||||
hash := d.Hash
|
||||
outpoint := wire.NewOutPoint(&hash, d.Index).String()
|
||||
deposit := &looprpc.Deposit{
|
||||
Id: d.ID[:],
|
||||
State: toClientDepositState(
|
||||
d.GetState(),
|
||||
),
|
||||
Outpoint: outpoint,
|
||||
Value: int64(d.Value),
|
||||
ConfirmationHeight: d.GetConfirmationHeight(),
|
||||
SwapHash: swapHash,
|
||||
deposit, err := s.rpcDeposit(d)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
clientDeposits = append(clientDeposits, deposit)
|
||||
}
|
||||
|
||||
return clientDeposits
|
||||
return clientDeposits, nil
|
||||
}
|
||||
|
||||
func (s *swapClientServer) rpcDeposit(d *deposit.Deposit) (
|
||||
*looprpc.Deposit, error) {
|
||||
|
||||
swapHash := make([]byte, 0, len(lntypes.Hash{}))
|
||||
if d.SwapHash != nil {
|
||||
swapHash = d.SwapHash[:]
|
||||
}
|
||||
|
||||
hash := d.Hash
|
||||
outpoint := wire.NewOutPoint(&hash, d.Index).String()
|
||||
deposit := &looprpc.Deposit{
|
||||
Id: d.ID[:],
|
||||
State: toClientDepositState(
|
||||
d.GetState(),
|
||||
),
|
||||
Outpoint: outpoint,
|
||||
Value: int64(d.Value),
|
||||
ConfirmationHeight: d.GetConfirmationHeight(),
|
||||
SwapHash: swapHash,
|
||||
}
|
||||
|
||||
if d.AddressParams == nil {
|
||||
return deposit, nil
|
||||
}
|
||||
|
||||
if s.staticAddressManager == nil {
|
||||
return nil, fmt.Errorf("static address manager not configured")
|
||||
}
|
||||
|
||||
staticAddress, err := s.staticAddressManager.GetTaprootAddress(
|
||||
d.AddressParams.ClientPubkey, d.AddressParams.ServerPubkey,
|
||||
int64(d.AddressParams.Expiry),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
deposit.StaticAddress = staticAddress.String()
|
||||
|
||||
return deposit, nil
|
||||
}
|
||||
|
||||
func toClientDepositState(state fsm.StateType) looprpc.DepositState {
|
||||
|
|
|
|||
|
|
@ -339,6 +339,17 @@ func TestListStaticAddressDepositsReturnsVisibleDeposits(t *testing.T) {
|
|||
available.SetState(deposit.Deposited)
|
||||
|
||||
addrMgr, lnd := newTestStaticAddressContext(t)
|
||||
addresses, err := addrMgr.GetAllAddresses(context.Background())
|
||||
require.NoError(t, err)
|
||||
require.Len(t, addresses, 1)
|
||||
available.AddressParams = addresses[0]
|
||||
|
||||
expectedAddr, err := addrMgr.GetTaprootAddress(
|
||||
addresses[0].ClientPubkey, addresses[0].ServerPubkey,
|
||||
int64(addresses[0].Expiry),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
server := &swapClientServer{
|
||||
depositManager: newTestDepositManager(available),
|
||||
staticAddressManager: addrMgr,
|
||||
|
|
@ -354,6 +365,10 @@ func TestListStaticAddressDepositsReturnsVisibleDeposits(t *testing.T) {
|
|||
t, available.OutPoint.String(),
|
||||
resp.FilteredDeposits[0].Outpoint,
|
||||
)
|
||||
require.Equal(
|
||||
t, expectedAddr.String(),
|
||||
resp.FilteredDeposits[0].StaticAddress,
|
||||
)
|
||||
}
|
||||
|
||||
// TestGetStaticAddressSummaryTotalsDeposits verifies visible deposits are
|
||||
|
|
|
|||
|
|
@ -416,6 +416,17 @@ func TestListStaticAddressSwapsPopulatesTimingAndCosts(t *testing.T) {
|
|||
}
|
||||
testDeposit.SetState(deposit.LoopedIn)
|
||||
|
||||
_, clientPubkey := mock_lnd.CreateKey(1)
|
||||
_, serverPubkey := mock_lnd.CreateKey(2)
|
||||
staticAddressParams := &script.Parameters{
|
||||
ID: 1,
|
||||
ClientPubkey: clientPubkey,
|
||||
ServerPubkey: serverPubkey,
|
||||
Expiry: staticAddressExpiry,
|
||||
PkScript: []byte("pkscript"),
|
||||
}
|
||||
testDeposit.AddressParams = staticAddressParams
|
||||
|
||||
initiationTime := time.Unix(1_234, 567).UTC()
|
||||
lastUpdateTime := time.Unix(2_345, 678).UTC()
|
||||
staticLoopIn := &loopin.StaticAddressLoopIn{
|
||||
|
|
@ -446,15 +457,8 @@ func TestListStaticAddressSwapsPopulatesTimingAndCosts(t *testing.T) {
|
|||
}, 1)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, clientPubkey := mock_lnd.CreateKey(1)
|
||||
_, serverPubkey := mock_lnd.CreateKey(2)
|
||||
addrStore := &mockAddressStore{
|
||||
params: []*script.Parameters{{
|
||||
ClientPubkey: clientPubkey,
|
||||
ServerPubkey: serverPubkey,
|
||||
Expiry: staticAddressExpiry,
|
||||
PkScript: []byte("pkscript"),
|
||||
}},
|
||||
params: []*script.Parameters{staticAddressParams},
|
||||
}
|
||||
addrMgr, err := address.NewManager(&address.ManagerConfig{
|
||||
Store: addrStore,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue