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  }