github.com/decred/dcrlnd@v0.7.6/lnrpc/initchainsyncrpc/initchainctrl_service.go (about) 1 package initchainsyncrpc 2 3 import ( 4 "fmt" 5 "time" 6 7 "github.com/decred/dcrlnd/lnwallet" 8 ) 9 10 // Server implements the initial chain sync gRPC service server. 11 type Server struct { 12 chainCtrl lnwallet.WalletController 13 chainCtrlSetChan chan struct{} 14 } 15 16 // A compile time check to ensure that Server fully implements the 17 // InitialChainSync gRPC service. 18 var _ InitialChainSyncServer = (*Server)(nil) 19 20 // NewInitCHainSyncService initializes a new InitChainSyncService. 21 func New() *Server { 22 return &Server{ 23 chainCtrlSetChan: make(chan struct{}), 24 } 25 } 26 27 // SetChainControl sets the internal chain/wallet controller. MUST only be 28 // called once. 29 func (s *Server) SetChainControl(cc lnwallet.WalletController) { 30 s.chainCtrl = cc 31 close(s.chainCtrlSetChan) 32 } 33 34 func (s *Server) SubscribeChainSync(sub *ChainSyncSubscription, svr InitialChainSync_SubscribeChainSyncServer) error { 35 // Wait until the chain control is set. 36 ccSet := false 37 for !ccSet { 38 select { 39 case <-s.chainCtrlSetChan: 40 ccSet = true 41 case <-svr.Context().Done(): 42 return svr.Context().Err() 43 } 44 } 45 46 var synced = false 47 delay := time.Millisecond 48 for !synced { 49 select { 50 case <-svr.Context().Done(): 51 return svr.Context().Err() 52 case <-s.chainCtrl.InitialSyncChannel(): 53 synced = true 54 case <-time.After(delay): 55 } 56 57 height, hash, ts, err := s.chainCtrl.BestBlock() 58 if err != nil { 59 return fmt.Errorf("unable to fetch current best block: %v", err) 60 } 61 updt := &ChainSyncUpdate{ 62 BlockHeight: height, 63 BlockHash: hash[:], 64 BlockTimestamp: ts, 65 Synced: synced, 66 } 67 if err := svr.Send(updt); err != nil { 68 return err 69 } 70 71 delay = 5 * time.Second 72 } 73 return nil 74 }