• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lightningnetwork / lnd / 13035292482

29 Jan 2025 03:59PM UTC coverage: 49.3% (-9.5%) from 58.777%
13035292482

Pull #9456

github

mohamedawnallah
docs: update release-notes-0.19.0.md

In this commit, we warn users about the removal
of RPCs `SendToRoute`, `SendToRouteSync`, `SendPayment`,
and `SendPaymentSync` in the next release 0.20.
Pull Request #9456: lnrpc+docs: deprecate warning `SendToRoute`, `SendToRouteSync`, `SendPayment`, and `SendPaymentSync` in Release 0.19

100634 of 204126 relevant lines covered (49.3%)

1.54 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

73.81
/chanacceptor/rpcacceptor.go
1
package chanacceptor
2

3
import (
4
        "encoding/hex"
5
        "errors"
6
        "fmt"
7
        "sync"
8
        "time"
9

10
        "github.com/btcsuite/btcd/btcutil"
11
        "github.com/btcsuite/btcd/chaincfg"
12
        "github.com/lightningnetwork/lnd/input"
13
        "github.com/lightningnetwork/lnd/lnrpc"
14
        "github.com/lightningnetwork/lnd/lnwallet/chancloser"
15
        "github.com/lightningnetwork/lnd/lnwire"
16
)
17

18
var (
19
        errShuttingDown = errors.New("server shutting down")
20

21
        // errCustomLength is returned when our custom error's length exceeds
22
        // our maximum.
23
        errCustomLength = fmt.Errorf("custom error message exceeds length "+
24
                "limit: %v", maxErrorLength)
25

26
        // errInvalidUpfrontShutdown is returned when we cannot parse the
27
        // upfront shutdown address returned.
28
        errInvalidUpfrontShutdown = fmt.Errorf("could not parse upfront " +
29
                "shutdown address")
30

31
        // errInsufficientReserve is returned when the reserve proposed by for
32
        // a channel is less than the dust limit originally supplied.
33
        errInsufficientReserve = fmt.Errorf("reserve lower than proposed dust " +
34
                "limit")
35

36
        // errAcceptWithError is returned when we get a response which accepts
37
        // a channel but ambiguously also sets a custom error message.
38
        errAcceptWithError = errors.New("channel acceptor response accepts " +
39
                "channel, but also includes custom error")
40

41
        // errMaxHtlcTooHigh is returned if our htlc count exceeds the number
42
        // hard-set by BOLT 2.
43
        errMaxHtlcTooHigh = fmt.Errorf("htlc limit exceeds spec limit of: %v",
44
                input.MaxHTLCNumber/2)
45

46
        // maxErrorLength is the maximum error length we allow the error we
47
        // send to our peer to be.
48
        maxErrorLength = 500
49
)
50

51
// chanAcceptInfo contains a request for a channel acceptor decision, and a
52
// channel that the response should be sent on.
53
type chanAcceptInfo struct {
54
        request  *ChannelAcceptRequest
55
        response chan *ChannelAcceptResponse
56
}
57

58
// RPCAcceptor represents the RPC-controlled variant of the ChannelAcceptor.
59
// One RPCAcceptor allows one RPC client.
60
type RPCAcceptor struct {
61
        // receive is a function from which we receive channel acceptance
62
        // decisions. Note that this function is expected to block.
63
        receive func() (*lnrpc.ChannelAcceptResponse, error)
64

65
        // send is a function which sends requests for channel acceptance
66
        // decisions into our rpc stream.
67
        send func(request *lnrpc.ChannelAcceptRequest) error
68

69
        // requests is a channel that we send requests for a acceptor response
70
        // into.
71
        requests chan *chanAcceptInfo
72

73
        // timeout is the amount of time we allow the channel acceptance
74
        // decision to take. This time includes the time to send a query to the
75
        // acceptor, and the time it takes to receive a response.
76
        timeout time.Duration
77

78
        // params are our current chain params.
79
        params *chaincfg.Params
80

81
        // done is closed when the rpc client terminates.
82
        done chan struct{}
83

84
        // quit is closed when lnd is shutting down.
85
        quit chan struct{}
86

87
        wg sync.WaitGroup
88
}
89

90
// Accept is a predicate on the ChannelAcceptRequest which is sent to the RPC
91
// client who will respond with the ultimate decision. This function passes the
92
// request into the acceptor's requests channel, and returns the response it
93
// receives, failing the request if the timeout elapses.
94
//
95
// NOTE: Part of the ChannelAcceptor interface.
96
func (r *RPCAcceptor) Accept(req *ChannelAcceptRequest) *ChannelAcceptResponse {
3✔
97
        respChan := make(chan *ChannelAcceptResponse, 1)
3✔
98

3✔
99
        newRequest := &chanAcceptInfo{
3✔
100
                request:  req,
3✔
101
                response: respChan,
3✔
102
        }
3✔
103

3✔
104
        // timeout is the time after which ChannelAcceptRequests expire.
3✔
105
        timeout := time.After(r.timeout)
3✔
106

3✔
107
        // Create a rejection response which we can use for the cases where we
3✔
108
        // reject the channel.
3✔
109
        rejectChannel := NewChannelAcceptResponse(
3✔
110
                false, errChannelRejected, nil, 0, 0, 0, 0, 0, 0, false,
3✔
111
        )
3✔
112

3✔
113
        // Send the request to the newRequests channel.
3✔
114
        select {
3✔
115
        case r.requests <- newRequest:
3✔
116

117
        case <-timeout:
×
118
                log.Errorf("RPCAcceptor returned false - reached timeout of %v",
×
119
                        r.timeout)
×
120
                return rejectChannel
×
121

122
        case <-r.done:
×
123
                return rejectChannel
×
124

125
        case <-r.quit:
×
126
                return rejectChannel
×
127
        }
128

129
        // Receive the response and return it. If no response has been received
130
        // in AcceptorTimeout, then return false.
131
        select {
3✔
132
        case resp := <-respChan:
3✔
133
                return resp
3✔
134

135
        case <-timeout:
×
136
                log.Errorf("RPCAcceptor returned false - reached timeout of %v",
×
137
                        r.timeout)
×
138
                return rejectChannel
×
139

140
        case <-r.done:
×
141
                return rejectChannel
×
142

143
        case <-r.quit:
×
144
                return rejectChannel
×
145
        }
146
}
147

148
// NewRPCAcceptor creates and returns an instance of the RPCAcceptor.
149
func NewRPCAcceptor(receive func() (*lnrpc.ChannelAcceptResponse, error),
150
        send func(*lnrpc.ChannelAcceptRequest) error, timeout time.Duration,
151
        params *chaincfg.Params, quit chan struct{}) *RPCAcceptor {
3✔
152

3✔
153
        return &RPCAcceptor{
3✔
154
                receive:  receive,
3✔
155
                send:     send,
3✔
156
                requests: make(chan *chanAcceptInfo),
3✔
157
                timeout:  timeout,
3✔
158
                params:   params,
3✔
159
                done:     make(chan struct{}),
3✔
160
                quit:     quit,
3✔
161
        }
3✔
162
}
3✔
163

164
// Run is the main loop for the RPC Acceptor. This function will block until
165
// it receives the signal that lnd is shutting down, or the rpc stream is
166
// cancelled by the client.
167
func (r *RPCAcceptor) Run() error {
3✔
168
        // Wait for our goroutines to exit before we return.
3✔
169
        defer r.wg.Wait()
3✔
170

3✔
171
        // Create a channel that responses from acceptors are sent into.
3✔
172
        responses := make(chan *lnrpc.ChannelAcceptResponse)
3✔
173

3✔
174
        // errChan is used by the receive loop to signal any errors that occur
3✔
175
        // during reading from the stream. This is primarily used to shutdown
3✔
176
        // the send loop in the case of an RPC client disconnecting.
3✔
177
        errChan := make(chan error, 1)
3✔
178

3✔
179
        // Start a goroutine to receive responses from the channel acceptor.
3✔
180
        // We expect the receive function to block, so it must be run in a
3✔
181
        // goroutine (otherwise we could not send more than one channel accept
3✔
182
        // request to the client).
3✔
183
        r.wg.Add(1)
3✔
184
        go func() {
6✔
185
                r.receiveResponses(errChan, responses)
3✔
186
                r.wg.Done()
3✔
187
        }()
3✔
188

189
        return r.sendAcceptRequests(errChan, responses)
3✔
190
}
191

192
// receiveResponses receives responses for our channel accept requests and
193
// dispatches them into the responses channel provided, sending any errors that
194
// occur into the error channel provided.
195
func (r *RPCAcceptor) receiveResponses(errChan chan error,
196
        responses chan *lnrpc.ChannelAcceptResponse) {
3✔
197

3✔
198
        for {
6✔
199
                resp, err := r.receive()
3✔
200
                if err != nil {
6✔
201
                        errChan <- err
3✔
202
                        return
3✔
203
                }
3✔
204

205
                var pendingID [32]byte
3✔
206
                copy(pendingID[:], resp.PendingChanId)
3✔
207

3✔
208
                openChanResp := &lnrpc.ChannelAcceptResponse{
3✔
209
                        Accept:          resp.Accept,
3✔
210
                        PendingChanId:   pendingID[:],
3✔
211
                        Error:           resp.Error,
3✔
212
                        UpfrontShutdown: resp.UpfrontShutdown,
3✔
213
                        CsvDelay:        resp.CsvDelay,
3✔
214
                        ReserveSat:      resp.ReserveSat,
3✔
215
                        InFlightMaxMsat: resp.InFlightMaxMsat,
3✔
216
                        MaxHtlcCount:    resp.MaxHtlcCount,
3✔
217
                        MinHtlcIn:       resp.MinHtlcIn,
3✔
218
                        MinAcceptDepth:  resp.MinAcceptDepth,
3✔
219
                        ZeroConf:        resp.ZeroConf,
3✔
220
                }
3✔
221

3✔
222
                // We have received a decision for one of our channel
3✔
223
                // acceptor requests.
3✔
224
                select {
3✔
225
                case responses <- openChanResp:
3✔
226

227
                case <-r.done:
×
228
                        return
×
229

230
                case <-r.quit:
×
231
                        return
×
232
                }
233
        }
234
}
235

236
// sendAcceptRequests handles channel acceptor requests sent to us by our
237
// Accept() function, dispatching them to our acceptor stream and coordinating
238
// return of responses to their callers.
239
func (r *RPCAcceptor) sendAcceptRequests(errChan chan error,
240
        responses chan *lnrpc.ChannelAcceptResponse) error {
3✔
241

3✔
242
        // Close the done channel to indicate that the acceptor is no longer
3✔
243
        // listening and any in-progress requests should be terminated.
3✔
244
        defer close(r.done)
3✔
245

3✔
246
        // Create a map of pending channel IDs to our original open channel
3✔
247
        // request and a response channel. We keep the original channel open
3✔
248
        // message so that we can validate our response against it.
3✔
249
        acceptRequests := make(map[[32]byte]*chanAcceptInfo)
3✔
250

3✔
251
        for {
6✔
252
                //nolint:ll
3✔
253
                select {
3✔
254
                // Consume requests passed to us from our Accept() function and
255
                // send them into our stream.
256
                case newRequest := <-r.requests:
3✔
257

3✔
258
                        req := newRequest.request
3✔
259
                        pendingChanID := req.OpenChanMsg.PendingChannelID
3✔
260

3✔
261
                        // Map the channel commitment type to its RPC
3✔
262
                        // counterpart. Also determine whether the zero-conf or
3✔
263
                        // scid-alias channel types are set.
3✔
264
                        var (
3✔
265
                                commitmentType lnrpc.CommitmentType
3✔
266
                                wantsZeroConf  bool
3✔
267
                                wantsScidAlias bool
3✔
268
                        )
3✔
269

3✔
270
                        if req.OpenChanMsg.ChannelType != nil {
6✔
271
                                channelFeatures := lnwire.RawFeatureVector(
3✔
272
                                        *req.OpenChanMsg.ChannelType,
3✔
273
                                )
3✔
274
                                switch {
3✔
275
                                case channelFeatures.OnlyContains(
276
                                        lnwire.ZeroConfRequired,
277
                                        lnwire.ScidAliasRequired,
278
                                        lnwire.ScriptEnforcedLeaseRequired,
279
                                        lnwire.AnchorsZeroFeeHtlcTxRequired,
280
                                        lnwire.StaticRemoteKeyRequired,
281
                                ):
×
282
                                        commitmentType = lnrpc.CommitmentType_SCRIPT_ENFORCED_LEASE
×
283

284
                                case channelFeatures.OnlyContains(
285
                                        lnwire.ZeroConfRequired,
286
                                        lnwire.ScriptEnforcedLeaseRequired,
287
                                        lnwire.AnchorsZeroFeeHtlcTxRequired,
288
                                        lnwire.StaticRemoteKeyRequired,
289
                                ):
3✔
290
                                        commitmentType = lnrpc.CommitmentType_SCRIPT_ENFORCED_LEASE
3✔
291

292
                                case channelFeatures.OnlyContains(
293
                                        lnwire.ScidAliasRequired,
294
                                        lnwire.ScriptEnforcedLeaseRequired,
295
                                        lnwire.AnchorsZeroFeeHtlcTxRequired,
296
                                        lnwire.StaticRemoteKeyRequired,
297
                                ):
×
298
                                        commitmentType = lnrpc.CommitmentType_SCRIPT_ENFORCED_LEASE
×
299

300
                                case channelFeatures.OnlyContains(
301
                                        lnwire.ScriptEnforcedLeaseRequired,
302
                                        lnwire.AnchorsZeroFeeHtlcTxRequired,
303
                                        lnwire.StaticRemoteKeyRequired,
304
                                ):
×
305
                                        commitmentType = lnrpc.CommitmentType_SCRIPT_ENFORCED_LEASE
×
306

307
                                case channelFeatures.OnlyContains(
308
                                        lnwire.ZeroConfRequired,
309
                                        lnwire.ScidAliasRequired,
310
                                        lnwire.AnchorsZeroFeeHtlcTxRequired,
311
                                        lnwire.StaticRemoteKeyRequired,
312
                                ):
×
313
                                        commitmentType = lnrpc.CommitmentType_ANCHORS
×
314

315
                                case channelFeatures.OnlyContains(
316
                                        lnwire.ZeroConfRequired,
317
                                        lnwire.AnchorsZeroFeeHtlcTxRequired,
318
                                        lnwire.StaticRemoteKeyRequired,
319
                                ):
3✔
320
                                        commitmentType = lnrpc.CommitmentType_ANCHORS
3✔
321

322
                                case channelFeatures.OnlyContains(
323
                                        lnwire.ScidAliasRequired,
324
                                        lnwire.AnchorsZeroFeeHtlcTxRequired,
325
                                        lnwire.StaticRemoteKeyRequired,
326
                                ):
3✔
327
                                        commitmentType = lnrpc.CommitmentType_ANCHORS
3✔
328

329
                                case channelFeatures.OnlyContains(
330
                                        lnwire.AnchorsZeroFeeHtlcTxRequired,
331
                                        lnwire.StaticRemoteKeyRequired,
332
                                ):
3✔
333
                                        commitmentType = lnrpc.CommitmentType_ANCHORS
3✔
334

335
                                case channelFeatures.OnlyContains(
336
                                        lnwire.SimpleTaprootChannelsRequiredStaging,
337
                                        lnwire.ZeroConfRequired,
338
                                        lnwire.ScidAliasRequired,
339
                                ):
×
340
                                        commitmentType = lnrpc.CommitmentType_SIMPLE_TAPROOT
×
341

342
                                case channelFeatures.OnlyContains(
343
                                        lnwire.SimpleTaprootChannelsRequiredStaging,
344
                                        lnwire.ZeroConfRequired,
345
                                ):
3✔
346
                                        commitmentType = lnrpc.CommitmentType_SIMPLE_TAPROOT
3✔
347

348
                                case channelFeatures.OnlyContains(
349
                                        lnwire.SimpleTaprootChannelsRequiredStaging,
350
                                        lnwire.ScidAliasRequired,
351
                                ):
×
352
                                        commitmentType = lnrpc.CommitmentType_SIMPLE_TAPROOT
×
353

354
                                case channelFeatures.OnlyContains(
355
                                        lnwire.SimpleTaprootChannelsRequiredStaging,
356
                                ):
×
357
                                        commitmentType = lnrpc.CommitmentType_SIMPLE_TAPROOT
×
358

359
                                case channelFeatures.OnlyContains(
360
                                        lnwire.SimpleTaprootOverlayChansRequired,
361
                                        lnwire.ZeroConfRequired,
362
                                        lnwire.ScidAliasRequired,
363
                                ):
×
364
                                        commitmentType = lnrpc.CommitmentType_SIMPLE_TAPROOT_OVERLAY
×
365

366
                                case channelFeatures.OnlyContains(
367
                                        lnwire.SimpleTaprootOverlayChansRequired,
368
                                        lnwire.ZeroConfRequired,
369
                                ):
×
370
                                        commitmentType = lnrpc.CommitmentType_SIMPLE_TAPROOT_OVERLAY
×
371

372
                                case channelFeatures.OnlyContains(
373
                                        lnwire.SimpleTaprootOverlayChansRequired,
374
                                        lnwire.ScidAliasRequired,
375
                                ):
×
376
                                        commitmentType = lnrpc.CommitmentType_SIMPLE_TAPROOT_OVERLAY
×
377

378
                                case channelFeatures.OnlyContains(
379
                                        lnwire.SimpleTaprootOverlayChansRequired,
380
                                ):
×
381
                                        commitmentType = lnrpc.CommitmentType_SIMPLE_TAPROOT_OVERLAY
×
382

383
                                case channelFeatures.OnlyContains(
384
                                        lnwire.StaticRemoteKeyRequired,
385
                                ):
3✔
386
                                        commitmentType = lnrpc.CommitmentType_STATIC_REMOTE_KEY
3✔
387

388
                                case channelFeatures.OnlyContains():
×
389
                                        commitmentType = lnrpc.CommitmentType_LEGACY
×
390

391
                                default:
×
392
                                        log.Warnf("Unhandled commitment type "+
×
393
                                                "in channel acceptor request: %v",
×
394
                                                req.OpenChanMsg.ChannelType)
×
395
                                }
396

397
                                if channelFeatures.IsSet(
3✔
398
                                        lnwire.ZeroConfRequired,
3✔
399
                                ) {
6✔
400

3✔
401
                                        wantsZeroConf = true
3✔
402
                                }
3✔
403

404
                                if channelFeatures.IsSet(
3✔
405
                                        lnwire.ScidAliasRequired,
3✔
406
                                ) {
6✔
407

3✔
408
                                        wantsScidAlias = true
3✔
409
                                }
3✔
410
                        }
411

412
                        acceptRequests[pendingChanID] = newRequest
3✔
413

3✔
414
                        // A ChannelAcceptRequest has been received, send it to the client.
3✔
415
                        chanAcceptReq := &lnrpc.ChannelAcceptRequest{
3✔
416
                                NodePubkey:       req.Node.SerializeCompressed(),
3✔
417
                                ChainHash:        req.OpenChanMsg.ChainHash[:],
3✔
418
                                PendingChanId:    req.OpenChanMsg.PendingChannelID[:],
3✔
419
                                FundingAmt:       uint64(req.OpenChanMsg.FundingAmount),
3✔
420
                                PushAmt:          uint64(req.OpenChanMsg.PushAmount),
3✔
421
                                DustLimit:        uint64(req.OpenChanMsg.DustLimit),
3✔
422
                                MaxValueInFlight: uint64(req.OpenChanMsg.MaxValueInFlight),
3✔
423
                                ChannelReserve:   uint64(req.OpenChanMsg.ChannelReserve),
3✔
424
                                MinHtlc:          uint64(req.OpenChanMsg.HtlcMinimum),
3✔
425
                                FeePerKw:         uint64(req.OpenChanMsg.FeePerKiloWeight),
3✔
426
                                CsvDelay:         uint32(req.OpenChanMsg.CsvDelay),
3✔
427
                                MaxAcceptedHtlcs: uint32(req.OpenChanMsg.MaxAcceptedHTLCs),
3✔
428
                                ChannelFlags:     uint32(req.OpenChanMsg.ChannelFlags),
3✔
429
                                CommitmentType:   commitmentType,
3✔
430
                                WantsZeroConf:    wantsZeroConf,
3✔
431
                                WantsScidAlias:   wantsScidAlias,
3✔
432
                        }
3✔
433

3✔
434
                        if err := r.send(chanAcceptReq); err != nil {
3✔
435
                                return err
×
436
                        }
×
437

438
                // Process newly received responses from our channel acceptor,
439
                // looking the original request up in our map of requests and
440
                // dispatching the response.
441
                case resp := <-responses:
3✔
442
                        // Look up the appropriate channel to send on given the
3✔
443
                        // pending ID. If a channel is found, send the response
3✔
444
                        // over it.
3✔
445
                        var pendingID [32]byte
3✔
446
                        copy(pendingID[:], resp.PendingChanId)
3✔
447
                        requestInfo, ok := acceptRequests[pendingID]
3✔
448
                        if !ok {
6✔
449
                                continue
3✔
450
                        }
451

452
                        // Validate the response we have received. If it is not
453
                        // valid, we log our error and proceed to deliver the
454
                        // rejection.
455
                        accept, acceptErr, shutdown, err := r.validateAcceptorResponse(
3✔
456
                                requestInfo.request.OpenChanMsg.DustLimit, resp,
3✔
457
                        )
3✔
458
                        if err != nil {
3✔
459
                                log.Errorf("Invalid acceptor response: %v", err)
×
460
                        }
×
461

462
                        requestInfo.response <- NewChannelAcceptResponse(
3✔
463
                                accept, acceptErr, shutdown,
3✔
464
                                uint16(resp.CsvDelay),
3✔
465
                                uint16(resp.MaxHtlcCount),
3✔
466
                                uint16(resp.MinAcceptDepth),
3✔
467
                                btcutil.Amount(resp.ReserveSat),
3✔
468
                                lnwire.MilliSatoshi(resp.InFlightMaxMsat),
3✔
469
                                lnwire.MilliSatoshi(resp.MinHtlcIn),
3✔
470
                                resp.ZeroConf,
3✔
471
                        )
3✔
472

3✔
473
                        // Delete the channel from the acceptRequests map.
3✔
474
                        delete(acceptRequests, pendingID)
3✔
475

476
                // If we failed to receive from our acceptor, we exit.
477
                case err := <-errChan:
3✔
478
                        log.Errorf("Received an error: %v, shutting down", err)
3✔
479
                        return err
3✔
480

481
                // Exit if we are shutting down.
482
                case <-r.quit:
×
483
                        return errShuttingDown
×
484
                }
485
        }
486
}
487

488
// validateAcceptorResponse validates the response we get from the channel
489
// acceptor, returning a boolean indicating whether to accept the channel, an
490
// error to send to the peer, and any validation errors that occurred.
491
func (r *RPCAcceptor) validateAcceptorResponse(dustLimit btcutil.Amount,
492
        req *lnrpc.ChannelAcceptResponse) (bool, error, lnwire.DeliveryAddress,
493
        error) {
3✔
494

3✔
495
        channelStr := hex.EncodeToString(req.PendingChanId)
3✔
496

3✔
497
        // Check that the max htlc count is within the BOLT 2 hard-limit of 483.
3✔
498
        // The initiating side should fail values above this anyway, but we
3✔
499
        // catch the invalid user input here.
3✔
500
        if req.MaxHtlcCount > input.MaxHTLCNumber/2 {
3✔
501
                log.Errorf("Max htlc count: %v for channel: %v is greater "+
×
502
                        "than limit of: %v", req.MaxHtlcCount, channelStr,
×
503
                        input.MaxHTLCNumber/2)
×
504

×
505
                return false, errChannelRejected, nil, errMaxHtlcTooHigh
×
506
        }
×
507

508
        // Ensure that the reserve that has been proposed, if it is set, is at
509
        // least the dust limit that was proposed by the remote peer. This is
510
        // required by BOLT 2.
511
        reserveSat := btcutil.Amount(req.ReserveSat)
3✔
512
        if reserveSat != 0 && reserveSat < dustLimit {
3✔
513
                log.Errorf("Remote reserve: %v sat for channel: %v must be "+
×
514
                        "at least equal to proposed dust limit: %v",
×
515
                        req.ReserveSat, channelStr, dustLimit)
×
516

×
517
                return false, errChannelRejected, nil, errInsufficientReserve
×
518
        }
×
519

520
        // Attempt to parse the upfront shutdown address provided.
521
        upfront, err := chancloser.ParseUpfrontShutdownAddress(
3✔
522
                req.UpfrontShutdown, r.params,
3✔
523
        )
3✔
524
        if err != nil {
3✔
525
                log.Errorf("Could not parse upfront shutdown for "+
×
526
                        "%v: %v", channelStr, err)
×
527

×
528
                return false, errChannelRejected, nil, errInvalidUpfrontShutdown
×
529
        }
×
530

531
        // Check that the custom error provided is valid.
532
        if len(req.Error) > maxErrorLength {
3✔
533
                return false, errChannelRejected, nil, errCustomLength
×
534
        }
×
535

536
        var haveCustomError = len(req.Error) != 0
3✔
537

3✔
538
        switch {
3✔
539
        // If accept is true, but we also have an error specified, we fail
540
        // because this result is ambiguous.
541
        case req.Accept && haveCustomError:
×
542
                return false, errChannelRejected, nil, errAcceptWithError
×
543

544
        // If we accept without an error message, we can just return a nil
545
        // error.
546
        case req.Accept:
3✔
547
                return true, nil, upfront, nil
3✔
548

549
        // If we reject the channel, and have a custom error, then we use it.
550
        case haveCustomError:
×
551
                return false, fmt.Errorf(req.Error), nil, nil
×
552

553
        // Otherwise, we have rejected the channel with no custom error, so we
554
        // just use a generic error to fail the channel.
555
        default:
3✔
556
                return false, errChannelRejected, nil, nil
3✔
557
        }
558
}
559

560
// A compile-time constraint to ensure RPCAcceptor implements the ChannelAcceptor
561
// interface.
562
var _ ChannelAcceptor = (*RPCAcceptor)(nil)
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc