mirror of
https://github.com/lightningnetwork/lnd.git
synced 2024-11-19 01:43:16 +01:00
sweep: make sure nil tx is handled
After previous commit, it should be clear that the tx may be failed to created in a `TxFailed` event. We now make sure to catch it to avoid panic.
This commit is contained in:
parent
184c191186
commit
9333ba4684
@ -75,7 +75,17 @@ const (
|
|||||||
// TxPublished is sent when the broadcast attempt is finished.
|
// TxPublished is sent when the broadcast attempt is finished.
|
||||||
TxPublished BumpEvent = iota
|
TxPublished BumpEvent = iota
|
||||||
|
|
||||||
// TxFailed is sent when the broadcast attempt fails.
|
// TxFailed is sent when the tx has encountered a fee-related error
|
||||||
|
// during its creation or broadcast, or an internal error from the fee
|
||||||
|
// bumper. In either case the inputs in this tx should be retried with
|
||||||
|
// either a different grouping strategy or an increased budget.
|
||||||
|
//
|
||||||
|
// NOTE: We also send this event when there's a third party spend
|
||||||
|
// event, and the sweeper will handle cleaning this up once it's
|
||||||
|
// confirmed.
|
||||||
|
//
|
||||||
|
// TODO(yy): Remove the above usage once we remove sweeping non-CPFP
|
||||||
|
// anchors.
|
||||||
TxFailed
|
TxFailed
|
||||||
|
|
||||||
// TxReplaced is sent when the original tx is replaced by a new one.
|
// TxReplaced is sent when the original tx is replaced by a new one.
|
||||||
@ -269,8 +279,10 @@ func (b *BumpResult) String() string {
|
|||||||
|
|
||||||
// Validate validates the BumpResult so it's safe to use.
|
// Validate validates the BumpResult so it's safe to use.
|
||||||
func (b *BumpResult) Validate() error {
|
func (b *BumpResult) Validate() error {
|
||||||
|
isFailureEvent := b.Event == TxFailed || b.Event == TxFatal
|
||||||
|
|
||||||
// Every result must have a tx except the fatal or failed case.
|
// Every result must have a tx except the fatal or failed case.
|
||||||
if b.Tx == nil && b.Event != TxFatal {
|
if b.Tx == nil && !isFailureEvent {
|
||||||
return fmt.Errorf("%w: nil tx", ErrInvalidBumpResult)
|
return fmt.Errorf("%w: nil tx", ErrInvalidBumpResult)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,10 +297,8 @@ func (b *BumpResult) Validate() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If it's a failed or fatal event, it must have an error.
|
// If it's a failed or fatal event, it must have an error.
|
||||||
if b.Event == TxFatal || b.Event == TxFailed {
|
if isFailureEvent && b.Err == nil {
|
||||||
if b.Err == nil {
|
return fmt.Errorf("%w: nil error", ErrInvalidBumpResult)
|
||||||
return fmt.Errorf("%w: nil error", ErrInvalidBumpResult)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If it's a confirmed event, it must have a fee rate and fee.
|
// If it's a confirmed event, it must have a fee rate and fee.
|
||||||
|
@ -91,13 +91,6 @@ func TestBumpResultValidate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
require.ErrorIs(t, b.Validate(), ErrInvalidBumpResult)
|
require.ErrorIs(t, b.Validate(), ErrInvalidBumpResult)
|
||||||
|
|
||||||
// A failed event without a tx will give an error.
|
|
||||||
b = BumpResult{
|
|
||||||
Event: TxFailed,
|
|
||||||
Err: errDummy,
|
|
||||||
}
|
|
||||||
require.ErrorIs(t, b.Validate(), ErrInvalidBumpResult)
|
|
||||||
|
|
||||||
// A fatal event without a failure reason will give an error.
|
// A fatal event without a failure reason will give an error.
|
||||||
b = BumpResult{
|
b = BumpResult{
|
||||||
Event: TxFailed,
|
Event: TxFailed,
|
||||||
@ -118,6 +111,13 @@ func TestBumpResultValidate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
require.NoError(t, b.Validate())
|
require.NoError(t, b.Validate())
|
||||||
|
|
||||||
|
// Tx is allowed to be nil in a TxFailed event.
|
||||||
|
b = BumpResult{
|
||||||
|
Event: TxFailed,
|
||||||
|
Err: errDummy,
|
||||||
|
}
|
||||||
|
require.NoError(t, b.Validate())
|
||||||
|
|
||||||
// Tx is allowed to be nil in a TxFatal event.
|
// Tx is allowed to be nil in a TxFatal event.
|
||||||
b = BumpResult{
|
b = BumpResult{
|
||||||
Event: TxFatal,
|
Event: TxFatal,
|
||||||
|
@ -1669,6 +1669,14 @@ func (s *UtxoSweeper) monitorFeeBumpResult(set InputSet,
|
|||||||
// in sweeper and rely solely on this event to mark
|
// in sweeper and rely solely on this event to mark
|
||||||
// inputs as Swept?
|
// inputs as Swept?
|
||||||
if r.Event == TxConfirmed || r.Event == TxFailed {
|
if r.Event == TxConfirmed || r.Event == TxFailed {
|
||||||
|
// Exit if the tx is failed to be created.
|
||||||
|
if r.Tx == nil {
|
||||||
|
log.Debugf("Received %v for nil tx, "+
|
||||||
|
"exit monitor", r.Event)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
log.Debugf("Received %v for sweep tx %v, exit "+
|
log.Debugf("Received %v for sweep tx %v, exit "+
|
||||||
"fee bump monitor", r.Event,
|
"fee bump monitor", r.Event,
|
||||||
r.Tx.TxHash())
|
r.Tx.TxHash())
|
||||||
@ -1694,7 +1702,10 @@ func (s *UtxoSweeper) handleBumpEventTxFailed(resp *bumpResp) {
|
|||||||
r := resp.result
|
r := resp.result
|
||||||
tx, err := r.Tx, r.Err
|
tx, err := r.Tx, r.Err
|
||||||
|
|
||||||
log.Warnf("Fee bump attempt failed for tx=%v: %v", tx.TxHash(), err)
|
if tx != nil {
|
||||||
|
log.Warnf("Fee bump attempt failed for tx=%v: %v", tx.TxHash(),
|
||||||
|
err)
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE: When marking the inputs as failed, we are using the input set
|
// NOTE: When marking the inputs as failed, we are using the input set
|
||||||
// instead of the inputs found in the tx. This is fine for current
|
// instead of the inputs found in the tx. This is fine for current
|
||||||
|
Loading…
Reference in New Issue
Block a user