github.com/decred/dcrlnd@v0.7.6/chainntnfs/chainscannotify/csnotify_dev.go (about) 1 //go:build dev 2 // +build dev 3 4 package csnotify 5 6 import ( 7 "fmt" 8 "time" 9 10 "github.com/decred/dcrd/chaincfg/chainhash" 11 "github.com/decred/dcrlnd/chainntnfs" 12 ) 13 14 // TODO(decred): Determine if the generateBlocks is needed. 15 // 16 // UnsafeStart starts the notifier with a specified best height and optional 17 // best hash. Its bestBlock and txNotifier are initialized with bestHeight and 18 // optionally bestHash. The parameter generateBlocks is necessary for the 19 // dcrd notifier to ensure we drain all notifications up to syncHeight, 20 // since if they are generated ahead of UnsafeStart the chainConn may start up 21 // with an outdated best block and miss sending ntfns. Used for testing. 22 func (n *ChainscanNotifier) UnsafeStart(bestHeight int64, bestHash *chainhash.Hash, 23 syncHeight int64, generateBlocks func() error) error { 24 25 n.txNotifier = chainntnfs.NewTxNotifier( 26 uint32(bestHeight), chainntnfs.ReorgSafetyLimit, 27 n.confirmHintCache, n.spendHintCache, n.chainParams, 28 ) 29 30 runAndLogOnError(n.ctx, n.chainConn.c.Run, "chainConn") 31 runAndLogOnError(n.ctx, n.tipWatcher.Run, "tipWatcher") 32 runAndLogOnError(n.ctx, n.historical.Run, "historical") 33 34 n.chainEvents = n.tipWatcher.ChainEvents(n.ctx) 35 36 n.wg.Add(1) 37 go n.handleChainEvents() 38 39 if generateBlocks != nil { 40 // Ensure no block notifications are pending when we start the 41 // notification dispatcher goroutine. 42 43 // First generate the blocks, then drain the notifications 44 // for the generated blocks. 45 if err := generateBlocks(); err != nil { 46 return err 47 } 48 49 timeout := time.After(60 * time.Second) 50 loop: 51 for { 52 select { 53 case ntfn := <-n.chainUpdates: 54 if int64(ntfn.height) >= syncHeight { 55 break loop 56 } 57 case <-timeout: 58 return fmt.Errorf("unable to catch up to height %d", 59 syncHeight) 60 } 61 } 62 } 63 64 // Run notificationDispatcher after setting the notifier's best block 65 // to avoid a race condition. 66 n.bestBlock = chainntnfs.BlockEpoch{ 67 Height: int32(bestHeight), Hash: bestHash, 68 } 69 if bestHash == nil { 70 hash, err := n.chainConn.GetBlockHash(int64(bestHeight)) 71 if err != nil { 72 return err 73 } 74 n.bestBlock.Hash = hash 75 } 76 77 n.wg.Add(1) 78 go n.notificationDispatcher() 79 80 return nil 81 }