Skip to content

Commit 89af6e3

Browse files
committed
staticaddr: multi-address handling in ListUnspentRaw
1 parent a8ed410 commit 89af6e3

File tree

7 files changed

+139
-104
lines changed

7 files changed

+139
-104
lines changed

loopd/swapclient_server.go

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1527,7 +1527,7 @@ func (s *swapClientServer) NewStaticAddress(ctx context.Context,
15271527
}
15281528

15291529
return &looprpc.NewStaticAddressResponse{
1530-
Address: staticAddress.String(),
1530+
Address: staticAddress,
15311531
Expiry: uint32(expiry),
15321532
}, nil
15331533
}
@@ -1539,13 +1539,17 @@ func (s *swapClientServer) ListUnspentDeposits(ctx context.Context,
15391539

15401540
// List all unspent utxos the wallet sees, regardless of the number of
15411541
// confirmations.
1542-
staticAddress, utxos, err := s.staticAddressManager.ListUnspentRaw(
1542+
utxos, err := s.staticAddressManager.ListUnspentRaw(
15431543
ctx, req.MinConfs, req.MaxConfs,
15441544
)
15451545
if err != nil {
15461546
return nil, err
15471547
}
15481548

1549+
if len(utxos) == 0 {
1550+
return &looprpc.ListUnspentDepositsResponse{}, nil
1551+
}
1552+
15491553
// ListUnspentRaw returns the unspent wallet view of the backing lnd
15501554
// wallet. It might be that deposits show up there that are actually
15511555
// not spendable because they already have been used but not yet spent
@@ -1593,7 +1597,7 @@ func (s *swapClientServer) ListUnspentDeposits(ctx context.Context,
15931597
}
15941598

15951599
// Any remaining outpoints in confirmedToCheck are ones that lnd knows
1596-
// about but we don't. These are new, unspent deposits.
1600+
// about, but we don't. These are new, unspent deposits.
15971601
for op := range confirmedToCheck {
15981602
isUnspent[op] = struct{}{}
15991603
}
@@ -1605,8 +1609,24 @@ func (s *swapClientServer) ListUnspentDeposits(ctx context.Context,
16051609
continue
16061610
}
16071611

1612+
params := s.staticAddressManager.GetParameters(u.PkScript)
1613+
if params == nil {
1614+
return nil, fmt.Errorf("unknown pkscript %x",
1615+
u.PkScript)
1616+
}
1617+
1618+
network, err := s.network.ChainParams()
1619+
if err != nil {
1620+
return nil, err
1621+
}
1622+
1623+
staticAddress, err := params.TaprootAddress(network)
1624+
if err != nil {
1625+
return nil, err
1626+
}
1627+
16081628
utxo := &looprpc.Utxo{
1609-
StaticAddress: staticAddress.String(),
1629+
StaticAddress: staticAddress,
16101630
AmountSat: int64(u.Value),
16111631
Confirmations: u.Confirmations,
16121632
Outpoint: u.OutPoint.String(),
@@ -1946,15 +1966,18 @@ func (s *swapClientServer) GetStaticAddressSummary(ctx context.Context,
19461966
return nil, err
19471967
}
19481968

1949-
address, err := s.staticAddressManager.GetTaprootAddress(
1950-
params.ClientPubkey, params.ServerPubkey, int64(params.Expiry),
1951-
)
1969+
network, err := s.network.ChainParams()
1970+
if err != nil {
1971+
return nil, err
1972+
}
1973+
1974+
address, err := params.TaprootAddress(network)
19521975
if err != nil {
19531976
return nil, err
19541977
}
19551978

19561979
return &looprpc.StaticAddressSummaryResponse{
1957-
StaticAddress: address.String(),
1980+
StaticAddress: address,
19581981
RelativeExpiryBlocks: uint64(params.Expiry),
19591982
TotalNumDeposits: uint32(totalNumDeposits),
19601983
ValueUnconfirmedSatoshis: valueUnconfirmed,

loopd/swapclient_server_test.go

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"github.com/btcsuite/btcd/chaincfg/chainhash"
1212
"github.com/btcsuite/btcd/wire"
1313
"github.com/btcsuite/btclog/v2"
14+
"github.com/lightninglabs/aperture/l402"
1415
"github.com/lightninglabs/lndclient"
1516
"github.com/lightninglabs/loop"
1617
"github.com/lightninglabs/loop/fsm"
@@ -967,6 +968,7 @@ func (s *mockDepositStore) AllDeposits(_ context.Context) ([]*deposit.Deposit,
967968
func TestListUnspentDeposits(t *testing.T) {
968969
ctx := context.Background()
969970
mock := mock_lnd.NewMockLnd()
971+
currentTokenMock := func() (*l402.Token, error) { return nil, nil }
970972

971973
// Prepare a single static address parameter set.
972974
_, client := mock_lnd.CreateKey(1)
@@ -983,12 +985,23 @@ func TestListUnspentDeposits(t *testing.T) {
983985

984986
// Build an address manager using our mock lnd and fake address store.
985987
addrMgr := address.NewManager(&address.ManagerConfig{
986-
Store: addrStore,
987-
WalletKit: mock.WalletKit,
988-
ChainParams: mock.ChainParams,
989-
// ChainNotifier and AddressClient are not needed for this test.
988+
Store: addrStore,
989+
WalletKit: mock.WalletKit,
990+
ChainParams: mock.ChainParams,
991+
ChainNotifier: mock.ChainNotifier,
992+
CurrentToken: currentTokenMock,
990993
}, 0)
991994

995+
initChan := make(chan struct{})
996+
go addrMgr.Run(t.Context(), initChan)
997+
998+
select {
999+
case <-initChan:
1000+
case <-t.Context().Done():
1001+
t.Fatalf("failed to initialize address manager: %v",
1002+
t.Context().Err())
1003+
}
1004+
9921005
// Construct several UTXOs with different confirmation counts.
9931006
makeUtxo := func(idx uint32, confs int64) *lnwallet.Utxo {
9941007
return &lnwallet.Utxo{
@@ -1041,6 +1054,7 @@ func TestListUnspentDeposits(t *testing.T) {
10411054
server := &swapClientServer{
10421055
staticAddressManager: addrMgr,
10431056
depositManager: depMgr,
1057+
network: lndclient.NetworkRegtest,
10441058
}
10451059

10461060
resp, err := server.ListUnspentDeposits(
@@ -1081,6 +1095,7 @@ func TestListUnspentDeposits(t *testing.T) {
10811095
server := &swapClientServer{
10821096
staticAddressManager: addrMgr,
10831097
depositManager: depMgr,
1098+
network: lndclient.NetworkRegtest,
10841099
}
10851100

10861101
resp, err := server.ListUnspentDeposits(
@@ -1111,6 +1126,7 @@ func TestListUnspentDeposits(t *testing.T) {
11111126
server := &swapClientServer{
11121127
staticAddressManager: addrMgr,
11131128
depositManager: depMgr,
1129+
network: lndclient.NetworkRegtest,
11141130
}
11151131

11161132
resp, err := server.ListUnspentDeposits(

staticaddr/address/interface.go

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@ import (
44
"context"
55

66
"github.com/btcsuite/btcd/btcec/v2"
7+
"github.com/btcsuite/btcd/btcec/v2/schnorr"
8+
"github.com/btcsuite/btcd/btcutil"
9+
"github.com/btcsuite/btcd/chaincfg"
10+
"github.com/lightninglabs/loop/staticaddr/script"
711
"github.com/lightninglabs/loop/staticaddr/version"
12+
"github.com/lightningnetwork/lnd/input"
813
"github.com/lightningnetwork/lnd/keychain"
914
)
1015

@@ -25,7 +30,7 @@ type Store interface {
2530
error)
2631
}
2732

28-
// Parameters holds all the necessary information for the 2-of-2 multisig
33+
// Parameters hold all the necessary information for the 2-of-2 multisig
2934
// address.
3035
type Parameters struct {
3136
// ClientPubkey is the client's pubkey for the static address. It is
@@ -53,3 +58,24 @@ type Parameters struct {
5358
// InitiationHeight is the height at which the address was initiated.
5459
InitiationHeight int32
5560
}
61+
62+
// TaprootAddress returns the taproot address of the static address.
63+
// Example: bc1phl46hgna56hfs0aykgccq29xl7z5z265vvs47lhfkkna749zmqyqa380nh.
64+
func (p *Parameters) TaprootAddress(network *chaincfg.Params) (string, error) {
65+
staticAddress, err := script.NewStaticAddress(
66+
input.MuSig2Version100RC2, int64(p.Expiry), p.ClientPubkey,
67+
p.ServerPubkey,
68+
)
69+
if err != nil {
70+
return "", err
71+
}
72+
73+
tpAddress, err := btcutil.NewAddressTaproot(
74+
schnorr.SerializePubKey(staticAddress.TaprootKey), network,
75+
)
76+
if err != nil {
77+
return "", err
78+
}
79+
80+
return tpAddress.String(), nil
81+
}

0 commit comments

Comments
 (0)