88 "github.com/btcsuite/btcd/btcec/v2"
99 "github.com/btcsuite/btcd/btcec/v2/schnorr"
1010 "github.com/btcsuite/btcd/btcutil"
11+ "github.com/btcsuite/btcd/wire"
1112 "github.com/lightninglabs/loop/loopdb"
1213 "github.com/lightninglabs/loop/staticaddr/script"
1314 "github.com/lightninglabs/loop/swap"
@@ -93,8 +94,9 @@ func (m *mockStaticAddressClient) ServerNewAddress(ctx context.Context,
9394
9495 args := m .Called (ctx , in , opts )
9596
96- return args .Get (0 ).(* swapserverrpc.ServerNewAddressResponse ),
97- args .Error (1 )
97+ resp , _ := args .Get (0 ).(* swapserverrpc.ServerNewAddressResponse )
98+
99+ return resp , args .Error (1 )
98100}
99101
100102// TestManager tests the static address manager generates the corerct static
@@ -128,6 +130,100 @@ func TestManager(t *testing.T) {
128130 require .EqualValues (t , defaultExpiry , expiry )
129131}
130132
133+ // TestNewAddressValidatesServerResponse tests that the untrusted
134+ // ServerNewAddress response is validated before the address script is created.
135+ func TestNewAddressValidatesServerResponse (t * testing.T ) {
136+ tests := []struct {
137+ name string
138+ resp * swapserverrpc.ServerNewAddressResponse
139+ expected string
140+ }{
141+ {
142+ name : "nil response" ,
143+ expected : "missing server new address response" ,
144+ },
145+ {
146+ name : "nil params" ,
147+ resp : & swapserverrpc.ServerNewAddressResponse {},
148+ expected : "missing server address parameters" ,
149+ },
150+ {
151+ name : "missing server key" ,
152+ resp : & swapserverrpc.ServerNewAddressResponse {
153+ Params : & swapserverrpc.ServerAddressParameters {
154+ Expiry : defaultExpiry ,
155+ },
156+ },
157+ expected : "missing server public key" ,
158+ },
159+ {
160+ name : "uncompressed server key" ,
161+ resp : & swapserverrpc.ServerNewAddressResponse {
162+ Params : & swapserverrpc.ServerAddressParameters {
163+ ServerKey : []byte {0x04 },
164+ Expiry : defaultExpiry ,
165+ },
166+ },
167+ expected : "server public key is not a compressed" ,
168+ },
169+ {
170+ name : "zero expiry" ,
171+ resp : newServerNewAddressResponse (0 ),
172+ expected : "static address CSV expiry must be non-zero" ,
173+ },
174+ {
175+ name : "seconds flag" ,
176+ resp : newServerNewAddressResponse (
177+ wire .SequenceLockTimeIsSeconds | 1 ,
178+ ),
179+ expected : "static address expiry does not fit into CSV" ,
180+ },
181+ {
182+ name : "disabled flag" ,
183+ resp : newServerNewAddressResponse (
184+ wire .SequenceLockTimeDisabled | 1 ,
185+ ),
186+ expected : "static address expiry does not fit into CSV" ,
187+ },
188+ {
189+ name : "reserved flag" ,
190+ resp : newServerNewAddressResponse (
191+ wire .SequenceLockTimeMask + 1 ,
192+ ),
193+ expected : "static address expiry does not fit into CSV" ,
194+ },
195+ {
196+ name : "too large" ,
197+ resp : newServerNewAddressResponse (
198+ maxStaticAddressCSVExpiry + 1 ,
199+ ),
200+ expected : "exceeds maximum" ,
201+ },
202+ }
203+
204+ for _ , test := range tests {
205+ t .Run (test .name , func (t * testing.T ) {
206+ testContext := NewAddressManagerTestContextWithResponse (
207+ t , test .resp ,
208+ )
209+
210+ _ , _ , err := testContext .manager .NewAddress (t .Context ())
211+ require .ErrorContains (t , err , test .expected )
212+ })
213+ }
214+ }
215+
216+ // TestNewAddressAcceptsMaxCSVExpiry tests the upper valid CSV boundary.
217+ func TestNewAddressAcceptsMaxCSVExpiry (t * testing.T ) {
218+ testContext := NewAddressManagerTestContextWithResponse (
219+ t , newServerNewAddressResponse (maxStaticAddressCSVExpiry ),
220+ )
221+
222+ _ , expiry , err := testContext .manager .NewAddress (t .Context ())
223+ require .NoError (t , err )
224+ require .EqualValues (t , maxStaticAddressCSVExpiry , expiry )
225+ }
226+
131227// GenerateExpectedTaprootAddress generates the expected taproot address that
132228// the predefined parameters are supposed to generate.
133229func GenerateExpectedTaprootAddress (t * ManagerTestContext ) (
@@ -170,6 +266,16 @@ type ManagerTestContext struct {
170266// NewAddressManagerTestContext creates a new test context for the static
171267// address manager.
172268func NewAddressManagerTestContext (t * testing.T ) * ManagerTestContext {
269+ return NewAddressManagerTestContextWithResponse (
270+ t , newServerNewAddressResponse (defaultExpiry ),
271+ )
272+ }
273+
274+ // NewAddressManagerTestContextWithResponse creates a new test context with a
275+ // custom ServerNewAddress response.
276+ func NewAddressManagerTestContextWithResponse (t * testing.T ,
277+ resp * swapserverrpc.ServerNewAddressResponse ) * ManagerTestContext {
278+
173279 ctxb , cancel := context .WithCancel (context .Background ())
174280 defer cancel ()
175281
@@ -184,14 +290,7 @@ func NewAddressManagerTestContext(t *testing.T) *ManagerTestContext {
184290
185291 mockStaticAddressClient .On (
186292 "ServerNewAddress" , mock .Anything , mock .Anything , mock .Anything ,
187- ).Return (
188- & swapserverrpc.ServerNewAddressResponse {
189- Params : & swapserverrpc.ServerAddressParameters {
190- ServerKey : defaultServerPubkeyBytes ,
191- Expiry : defaultExpiry ,
192- },
193- }, nil ,
194- )
293+ ).Return (resp , nil )
195294
196295 cfg := & ManagerConfig {
197296 Store : store ,
@@ -215,3 +314,14 @@ func NewAddressManagerTestContext(t *testing.T) *ManagerTestContext {
215314 mockStaticAddressClient : mockStaticAddressClient ,
216315 }
217316}
317+
318+ // newServerNewAddressResponse returns a valid server response with the given
319+ // CSV expiry.
320+ func newServerNewAddressResponse (expiry uint32 ) * swapserverrpc.ServerNewAddressResponse {
321+ return & swapserverrpc.ServerNewAddressResponse {
322+ Params : & swapserverrpc.ServerAddressParameters {
323+ ServerKey : defaultServerPubkeyBytes ,
324+ Expiry : expiry ,
325+ },
326+ }
327+ }
0 commit comments