github.com/decred/dcrlnd@v0.7.6/dcrlnd.go (about) 1 package dcrlnd 2 3 import ( 4 "context" 5 "crypto/rand" 6 "errors" 7 "fmt" 8 "io" 9 "time" 10 11 "decred.org/dcrwallet/v4/wallet" 12 "github.com/decred/dcrlnd/chainreg" 13 "github.com/decred/dcrlnd/lnrpc/initchainsyncrpc" 14 "github.com/decred/dcrlnd/lnwallet" 15 "github.com/decred/dcrlnd/lnwallet/dcrwallet" 16 walletloader "github.com/decred/dcrlnd/lnwallet/dcrwallet/loader" 17 "github.com/decred/dcrlnd/lnwallet/remotedcrwallet" 18 "github.com/decred/dcrlnd/signal" 19 "github.com/decred/slog" 20 "gopkg.in/macaroon-bakery.v2/bakery" 21 ) 22 23 var errShutdownRequested = errors.New("shutdown requested") 24 25 var initChainSyncPermissions = map[string][]bakery.Op{ 26 "/initialchainsyncrpc.InitialChainSync/SubscribeChainSync": {{ 27 Entity: "onchain", 28 Action: "read", 29 }}, 30 } 31 32 // waitForInitialChainSync waits until the initial chain sync is completed 33 // before returning. It creates a gRPC service to listen to requests to provide 34 // the sync progress. 35 func waitForInitialChainSync(activeChainControl *chainreg.ChainControl, 36 interceptor *signal.Interceptor, svc *initchainsyncrpc.Server) error { 37 38 _, bestHeight, err := activeChainControl.ChainIO.GetBestBlock() 39 if err != nil { 40 return err 41 } 42 ltndLog.Infof("Waiting for chain backend to finish sync, "+ 43 "start_height=%v", bestHeight) 44 45 svc.SetChainControl(activeChainControl.Wallet) 46 47 // Wait until the initial sync is done. 48 select { 49 case <-interceptor.ShutdownChannel(): 50 return errShutdownRequested 51 case <-activeChainControl.Wallet.InitialSyncChannel(): 52 } 53 54 _, bestHeight, err = activeChainControl.ChainIO.GetBestBlock() 55 if err != nil { 56 return err 57 } 58 ltndLog.Infof("Chain backend is fully synced (end_height=%v)!", 59 bestHeight) 60 61 return nil 62 } 63 64 func noSeedBackupWalletInit(ctx context.Context, cfg *Config, privPass, pubPass []byte) (*wallet.Wallet, error) { 65 66 netDir := dcrwallet.NetworkDir( 67 cfg.Decred.ChainDir, cfg.ActiveNetParams.Params, 68 ) 69 loader := walletloader.NewLoader( 70 cfg.ActiveNetParams.Params, netDir, wallet.DefaultGapLimit, 71 // loaderOpts..., 72 ) 73 exists, err := loader.WalletExists() 74 if err != nil { 75 return nil, err 76 } 77 if exists { 78 return loader.OpenExistingWallet(ctx, pubPass) 79 } 80 81 var seed [32]byte 82 if _, err := io.ReadFull(rand.Reader, seed[:]); err != nil { 83 return nil, err 84 } 85 return loader.CreateNewWallet(ctx, pubPass, privPass, seed[:], 86 time.Now().Add(-time.Hour*24)) 87 } 88 89 type RemoteWalletBuilder struct { 90 logger slog.Logger 91 } 92 93 func (rb *RemoteWalletBuilder) BuildChainControl( 94 partialChainControl *chainreg.PartialChainControl, 95 walletConfig *chainreg.WalletConfig) (*chainreg.ChainControl, func(), error) { 96 97 cfg := partialChainControl.Cfg 98 99 // Initialize an RPC syncer for this wallet and use it as 100 // blockchain IO source. 101 dcrwConfig := &remotedcrwallet.Config{ 102 PrivatePass: walletConfig.PrivatePass, 103 NetParams: cfg.ActiveNetParams.Params, 104 DB: cfg.FullDB, 105 Conn: partialChainControl.Cfg.WalletUnlockParams.Conn, 106 AccountNumber: walletConfig.AccountNb, 107 BlockCache: cfg.BlockCache, 108 } 109 110 walletController, err := remotedcrwallet.New(*dcrwConfig) 111 if err != nil { 112 err := fmt.Errorf("unable to create remote wallet "+ 113 "controller: %v\n", err) 114 return nil, nil, err 115 } 116 117 // Create, and start the lnwallet, which handles the core payment 118 // channel logic, and exposes control via proxy state machines. 119 lnWalletConfig := lnwallet.Config{ 120 Database: partialChainControl.Cfg.ChanStateDB, 121 Notifier: partialChainControl.ChainNotifier, 122 WalletController: walletController, 123 Signer: walletController, 124 FeeEstimator: partialChainControl.FeeEstimator, 125 SecretKeyRing: walletController, 126 ChainIO: walletController, 127 DefaultConstraints: partialChainControl.ChannelConstraints, 128 NetParams: *partialChainControl.Cfg.ActiveNetParams.Params, 129 } 130 131 // We've created the wallet configuration now, so we can finish 132 // initializing the main chain control. 133 activeChainControl, cleanUp, err := chainreg.NewChainControl( 134 lnWalletConfig, walletController, partialChainControl, 135 ) 136 if err != nil { 137 err := fmt.Errorf("unable to create chain control: %v", err) 138 rb.logger.Error(err) 139 return nil, nil, err 140 } 141 142 return activeChainControl, cleanUp, nil 143 }