From 4c292f179faf4ccbb4902e57c73405889426024e Mon Sep 17 00:00:00 2001 From: Boris Nagaev Date: Mon, 10 Mar 2025 19:36:54 -0300 Subject: [PATCH] staticaddr: fix race conditions in current height Make the current height an atomic variable in staticaddr/address/manager.go and in staticaddr/withdraw/manager.go. Removed the initiation height from staticaddr/deposit/manager.go (not needed). --- loopd/daemon.go | 10 +--------- staticaddr/address/manager.go | 9 +++++---- staticaddr/deposit/manager.go | 7 +------ staticaddr/deposit/manager_test.go | 5 +---- staticaddr/withdraw/manager.go | 7 ++++--- 5 files changed, 12 insertions(+), 26 deletions(-) diff --git a/loopd/daemon.go b/loopd/daemon.go index 9bb5e622..d35d5fc5 100644 --- a/loopd/daemon.go +++ b/loopd/daemon.go @@ -861,16 +861,8 @@ func (d *Daemon) initialize(withMacaroonService bool) error { go func() { defer d.wg.Done() - // Lnd's GetInfo call supplies us with the current block - // height. - info, err := d.lnd.Client.GetInfo(d.mainCtx) - if err != nil { - d.internalErrChan <- err - return - } - infof("Starting static address deposit manager...") - err = depositManager.Run(d.mainCtx, info.BlockHeight) + err = depositManager.Run(d.mainCtx) if err != nil && !errors.Is(context.Canceled, err) { d.internalErrChan <- err } diff --git a/staticaddr/address/manager.go b/staticaddr/address/manager.go index 4cb5391c..96e9cdbf 100644 --- a/staticaddr/address/manager.go +++ b/staticaddr/address/manager.go @@ -5,6 +5,7 @@ import ( "context" "fmt" "sync" + "sync/atomic" "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2/schnorr" @@ -52,7 +53,7 @@ type Manager struct { sync.Mutex - currentHeight int32 + currentHeight atomic.Int32 } // NewManager creates a new address manager. @@ -74,7 +75,7 @@ func (m *Manager) Run(ctx context.Context) error { for { select { case currentHeight := <-newBlockChan: - m.currentHeight = currentHeight + m.currentHeight.Store(currentHeight) case err = <-newBlockErrChan: return err @@ -111,7 +112,7 @@ func (m *Manager) NewAddress(ctx context.Context) (*btcutil.AddressTaproot, m.Unlock() // Ensure that we have that we have a sane current block height. - if m.currentHeight == 0 { + if m.currentHeight.Load() == 0 { return nil, fmt.Errorf("current block height is unknown") } @@ -176,7 +177,7 @@ func (m *Manager) NewAddress(ctx context.Context) (*btcutil.AddressTaproot, ProtocolVersion: version.AddressProtocolVersion( protocolVersion, ), - InitiationHeight: m.currentHeight, + InitiationHeight: m.currentHeight.Load(), } err = m.cfg.Store.CreateStaticAddress(ctx, addrParams) if err != nil { diff --git a/staticaddr/deposit/manager.go b/staticaddr/deposit/manager.go index efaef97a..c6c34234 100644 --- a/staticaddr/deposit/manager.go +++ b/staticaddr/deposit/manager.go @@ -84,9 +84,6 @@ type Manager struct { // activeDeposits contains all the active static address outputs. activeDeposits map[wire.OutPoint]*FSM - // initiationHeight stores the currently best known block height. - initiationHeight uint32 - // deposits contains all the deposits that have ever been made to the // static address. This field is used to store and recover deposits. It // also serves as basis for reconciliation of newly detected deposits by @@ -111,9 +108,7 @@ func NewManager(cfg *ManagerConfig) *Manager { } // Run runs the address manager. -func (m *Manager) Run(ctx context.Context, currentHeight uint32) error { - m.initiationHeight = currentHeight - +func (m *Manager) Run(ctx context.Context) error { newBlockChan, newBlockErrChan, err := m.cfg.ChainNotifier.RegisterBlockEpochNtfn(ctx) //nolint:lll if err != nil { return err diff --git a/staticaddr/deposit/manager_test.go b/staticaddr/deposit/manager_test.go index d943a32f..dc67393b 100644 --- a/staticaddr/deposit/manager_test.go +++ b/staticaddr/deposit/manager_test.go @@ -219,10 +219,7 @@ func TestManager(t *testing.T) { // Start the deposit manager. go func() { - err := testContext.manager.Run( - ctx, uint32(testContext.mockLnd.Height), - ) - require.NoError(t, err) + require.NoError(t, testContext.manager.Run(ctx)) }() // Ensure that the manager has been initialized. diff --git a/staticaddr/withdraw/manager.go b/staticaddr/withdraw/manager.go index 1a60b37b..2de21214 100644 --- a/staticaddr/withdraw/manager.go +++ b/staticaddr/withdraw/manager.go @@ -6,6 +6,7 @@ import ( "fmt" "reflect" "strings" + "sync/atomic" "github.com/btcsuite/btcd/btcec/v2/schnorr" "github.com/btcsuite/btcd/btcec/v2/schnorr/musig2" @@ -106,7 +107,7 @@ type Manager struct { errChan chan error // initiationHeight stores the currently best known block height. - initiationHeight uint32 + initiationHeight atomic.Uint32 // finalizedWithdrawalTx are the finalized withdrawal transactions that // are published to the network and re-published on block arrivals. @@ -127,7 +128,7 @@ func NewManager(cfg *ManagerConfig) *Manager { // Run runs the deposit withdrawal manager. func (m *Manager) Run(ctx context.Context, currentHeight uint32) error { - m.initiationHeight = currentHeight + m.initiationHeight.Store(currentHeight) newBlockChan, newBlockErrChan, err := m.cfg.ChainNotifier.RegisterBlockEpochNtfn(ctx) @@ -479,7 +480,7 @@ func (m *Manager) handleWithdrawal(ctx context.Context, confChan, errChan, err := m.cfg.ChainNotifier.RegisterConfirmationsNtfn( ctx, &txHash, withdrawalPkScript, MinConfs, - int32(m.initiationHeight), + int32(m.initiationHeight.Load()), ) if err != nil { return err