Skip to content

Commit

Permalink
chain: add rescanMtx to resolve rescan segfault
Browse files Browse the repository at this point in the history
Add a mutex to synchronize access to the rescan prop of the
neutrino client.  Make calls to Rescan and NotifyReceived
require the rescan mutex lock to execute.  Resolve the segmentation
fault in the TestNeutrinoClientNotifyReceivedRescan unit test.
  • Loading branch information
MStreet3 committed Dec 2, 2022
1 parent 30824ef commit 90844c7
Showing 1 changed file with 22 additions and 0 deletions.
22 changes: 22 additions & 0 deletions chain/neutrino.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,14 @@ type NeutrinoClient struct {
chainParams *chaincfg.Params

// We currently support only one rescan/notification goroutine per client.
// Therefore there can only be one instance of the rescan object and
// the rescanMtx synchronizes its access. Calls to the NotifyReceived
// and Rescan methods of the client must hold the rescan mutex lock for
// the length of their execution to ensure that all operations that
// affect the rescan object are atomic.
rescan rescanner
newRescan newRescanFunc
rescanMtx sync.Mutex

enqueueNotification chan interface{}
dequeueNotification chan interface{}
Expand All @@ -46,6 +52,14 @@ type NeutrinoClient struct {
finished bool
isRescan bool

// The clientMtx synchronizes access to the state variables of the client.
//
// TODO(mstreet3): Currently the clientMtx synchronizes access to the
// rescanQuit and rescanErr channels, which cancel the current rescan
// goroutine when closed and is updated each time a new rescan goroutine
// is created, respectively. All state related to the rescan goroutine
// should ideally be synchronized by the same lock or via some other
// shared mechanism.
clientMtx sync.Mutex
}

Expand Down Expand Up @@ -351,6 +365,10 @@ func (s *NeutrinoClient) pollCFilter(hash *chainhash.Hash) (*gcs.Filter, error)
func (s *NeutrinoClient) Rescan(startHash *chainhash.Hash, addrs []btcutil.Address,
outPoints map[wire.OutPoint]btcutil.Address) error {

// Obtain and hold the rescan mutex lock for the duration of the call.
s.rescanMtx.Lock()
defer s.rescanMtx.Unlock()

s.clientMtx.Lock()
if !s.started {
s.clientMtx.Unlock()
Expand Down Expand Up @@ -458,6 +476,10 @@ func (s *NeutrinoClient) NotifyBlocks() error {

// NotifyReceived replicates the RPC client's NotifyReceived command.
func (s *NeutrinoClient) NotifyReceived(addrs []btcutil.Address) error {
// Obtain and hold the rescan mutex lock for the duration of the call.
s.rescanMtx.Lock()
defer s.rescanMtx.Unlock()

s.clientMtx.Lock()

// If we have a rescan running, we just need to add the appropriate
Expand Down

0 comments on commit 90844c7

Please sign in to comment.