mirror of
https://github.com/lightninglabs/loop.git
synced 2026-08-13 12:33:03 +02:00
staticaddr/deposit: sweep with owning address keys
Build timeout sweeps from each deposit own script, expiry, and key locator. Derived-address deposits can now use their unilateral recovery path without falling back to the legacy root parameters.
This commit is contained in:
parent
eb03aacf6c
commit
fd1c651a47
3 changed files with 66 additions and 24 deletions
|
|
@ -6,7 +6,6 @@ import (
|
|||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightninglabs/lndclient"
|
||||
"github.com/lightninglabs/loop/fsm"
|
||||
|
|
@ -27,9 +26,15 @@ func (f *FSM) PublishDepositExpirySweepAction(ctx context.Context,
|
|||
|
||||
msgTx := wire.NewMsgTx(2)
|
||||
|
||||
params, err := f.cfg.AddressManager.GetStaticAddressParameters(ctx)
|
||||
if f.deposit.AddressParams == nil {
|
||||
return f.HandleError(fmt.Errorf("missing static address " +
|
||||
"parameters"))
|
||||
}
|
||||
params := f.deposit.AddressParams
|
||||
|
||||
address, err := f.deposit.GetStaticAddressScript()
|
||||
if err != nil {
|
||||
return fsm.OnError
|
||||
return f.HandleError(err)
|
||||
}
|
||||
|
||||
// Add the deposit outpoint as input to the transaction.
|
||||
|
|
@ -96,11 +101,6 @@ func (f *FSM) PublishDepositExpirySweepAction(ctx context.Context,
|
|||
return f.HandleError(err)
|
||||
}
|
||||
|
||||
address, err := f.cfg.AddressManager.GetStaticAddress(ctx)
|
||||
if err != nil {
|
||||
return f.HandleError(err)
|
||||
}
|
||||
|
||||
sig := rawSigs[0]
|
||||
msgTx.TxIn[0].Witness, err = address.GenTimeoutWitness(sig)
|
||||
if err != nil {
|
||||
|
|
@ -131,14 +131,10 @@ func (f *FSM) PublishDepositExpirySweepAction(ctx context.Context,
|
|||
func (f *FSM) WaitForExpirySweepAction(ctx context.Context,
|
||||
_ fsm.EventContext) fsm.EventType {
|
||||
|
||||
var txID *chainhash.Hash
|
||||
// Only pass the txid if we know it from our own publication.
|
||||
if f.deposit.ExpirySweepTxid != (chainhash.Hash{}) {
|
||||
txID = &f.deposit.ExpirySweepTxid
|
||||
}
|
||||
|
||||
// Register by script only so an RBF replacement of the timeout sweep is
|
||||
// still detected after restart with a stale ExpirySweepTxid.
|
||||
spendChan, errSpendChan, err := f.cfg.ChainNotifier.RegisterConfirmationsNtfn( //nolint:lll
|
||||
ctx, txID, f.deposit.TimeOutSweepPkScript, DefaultConfTarget,
|
||||
ctx, nil, f.deposit.TimeOutSweepPkScript, DefaultConfTarget,
|
||||
int32(f.deposit.GetConfirmationHeight()),
|
||||
)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ import (
|
|||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightninglabs/loop/fsm"
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
|
@ -52,6 +54,50 @@ func TestFinalizeDepositActionDoesNotBlock(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestWaitForExpirySweepActionRegistersByScriptOnly(t *testing.T) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
||||
defer cancel()
|
||||
|
||||
timeoutPkScript := []byte{0x51, 0x20, 0x01}
|
||||
confChan := make(chan *chainntnfs.TxConfirmation, 1)
|
||||
errChan := make(chan error, 1)
|
||||
|
||||
chainNotifier := &MockChainNotifier{}
|
||||
chainNotifier.On(
|
||||
"RegisterConfirmationsNtfn",
|
||||
mock.Anything,
|
||||
mock.MatchedBy(func(txid *chainhash.Hash) bool {
|
||||
return txid == nil
|
||||
}),
|
||||
timeoutPkScript,
|
||||
int32(DefaultConfTarget),
|
||||
int32(42),
|
||||
).Return(confChan, errChan, nil).Once()
|
||||
|
||||
depositFSM := &FSM{
|
||||
cfg: &ManagerConfig{
|
||||
ChainNotifier: chainNotifier,
|
||||
},
|
||||
deposit: &Deposit{
|
||||
ConfirmationHeight: 42,
|
||||
ExpirySweepTxid: chainhash.Hash{9},
|
||||
TimeOutSweepPkScript: timeoutPkScript,
|
||||
},
|
||||
}
|
||||
|
||||
confirmedTx := wire.NewMsgTx(2)
|
||||
confirmedTx.AddTxOut(&wire.TxOut{
|
||||
Value: 1000,
|
||||
PkScript: timeoutPkScript,
|
||||
})
|
||||
confChan <- &chainntnfs.TxConfirmation{Tx: confirmedTx}
|
||||
|
||||
event := depositFSM.WaitForExpirySweepAction(ctx, nil)
|
||||
require.Equal(t, OnExpirySwept, event)
|
||||
require.Equal(t, confirmedTx.TxHash(), depositFSM.deposit.ExpirySweepTxid)
|
||||
chainNotifier.AssertExpectations(t)
|
||||
}
|
||||
|
||||
// TestFinalizeDepositActionIgnoresRequestCancellation ensures the cleanup
|
||||
// notification is tied to the FSM lifetime, not the caller's request context.
|
||||
func TestFinalizeDepositActionIgnoresRequestCancellation(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -181,13 +181,13 @@ func NewFSM(ctx context.Context, deposit *Deposit, cfg *ManagerConfig,
|
|||
finalizedDepositChan chan wire.OutPoint,
|
||||
recoverStateMachine bool) (*FSM, error) {
|
||||
|
||||
params, err := cfg.AddressManager.GetStaticAddressParameters(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to get static address "+
|
||||
"parameters: %w", err)
|
||||
if deposit.AddressParams == nil {
|
||||
return nil, fmt.Errorf("missing deposit static address " +
|
||||
"parameters")
|
||||
}
|
||||
params := deposit.AddressParams
|
||||
|
||||
address, err := cfg.AddressManager.GetStaticAddress(ctx)
|
||||
address, err := deposit.GetStaticAddressScript()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to get static address: %w", err)
|
||||
}
|
||||
|
|
@ -535,10 +535,10 @@ func (f *FSM) Errorf(format string, args ...any) {
|
|||
}
|
||||
|
||||
// SignDescriptor returns the sign descriptor for the static address output.
|
||||
func (f *FSM) SignDescriptor(ctx context.Context) (*lndclient.SignDescriptor,
|
||||
func (f *FSM) SignDescriptor(_ context.Context) (*lndclient.SignDescriptor,
|
||||
error) {
|
||||
|
||||
address, err := f.cfg.AddressManager.GetStaticAddress(ctx)
|
||||
address, err := f.deposit.GetStaticAddressScript()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -546,10 +546,10 @@ func (f *FSM) SignDescriptor(ctx context.Context) (*lndclient.SignDescriptor,
|
|||
return &lndclient.SignDescriptor{
|
||||
WitnessScript: address.TimeoutLeaf.Script,
|
||||
KeyDesc: keychain.KeyDescriptor{
|
||||
PubKey: f.params.ClientPubkey,
|
||||
PubKey: f.deposit.AddressParams.ClientPubkey,
|
||||
},
|
||||
Output: wire.NewTxOut(
|
||||
int64(f.deposit.Value), f.params.PkScript,
|
||||
int64(f.deposit.Value), f.deposit.AddressParams.PkScript,
|
||||
),
|
||||
HashType: txscript.SigHashDefault,
|
||||
InputIndex: 0,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue