github.com/mit-dci/lit@v0.0.0-20221102210550-8c3d3b49f2ce/qln/init.go (about)

     1  package qln
     2  
     3  import (
     4  	"fmt"
     5  	"path/filepath"
     6  	"sync"
     7  
     8  	"github.com/boltdb/bolt"
     9  	"github.com/mit-dci/lit/btcutil"
    10  	"github.com/mit-dci/lit/btcutil/hdkeychain"
    11  	"github.com/mit-dci/lit/coinparam"
    12  	"github.com/mit-dci/lit/db/lnbolt" // TODO Abstract this more.
    13  	"github.com/mit-dci/lit/dlc"
    14  	"github.com/mit-dci/lit/eventbus"
    15  	"github.com/mit-dci/lit/lncore"
    16  	"github.com/mit-dci/lit/lnp2p"
    17  	"github.com/mit-dci/lit/logging"
    18  	"github.com/mit-dci/lit/portxo"
    19  	"github.com/mit-dci/lit/wallit"
    20  	"github.com/mit-dci/lit/watchtower"
    21  )
    22  
    23  // NewLitNode starts up a lit node.  Needs priv key, and a path.
    24  // Does not activate a subwallet; do that after init.
    25  func NewLitNode(privKey *[32]byte, path string, trackerURL string, proxyURL string, nat string) (*LitNode, error) {
    26  
    27  	var err error
    28  
    29  	// Maybe make a new parameter set for "LN".. meh
    30  	// TODO change this to a non-coin
    31  	rootPrivKey, err := hdkeychain.NewMaster(privKey[:], &coinparam.TestNet3Params)
    32  	if err != nil {
    33  		return nil, err
    34  	}
    35  
    36  	nd := new(LitNode)
    37  	nd.LitFolder = path
    38  
    39  	litdbpath := filepath.Join(nd.LitFolder, "ln.db")
    40  	err = nd.OpenDB(litdbpath)
    41  	if err != nil {
    42  		return nil, err
    43  	}
    44  
    45  	db2 := &lnbolt.LitBoltDB{}
    46  	var dbx lncore.LitStorage
    47  	dbx = db2
    48  	err = dbx.Open(filepath.Join(nd.LitFolder, "db2"))
    49  	if err != nil {
    50  		return nil, err
    51  	}
    52  	nd.NewLitDB = dbx
    53  	err = nd.NewLitDB.Check()
    54  	if err != nil {
    55  		return nil, err
    56  	}
    57  
    58  	// Event system setup.
    59  	ebus := eventbus.NewEventBus()
    60  	nd.Events = &ebus
    61  
    62  	// Peer manager
    63  	nd.PeerMan, err = lnp2p.NewPeerManager(rootPrivKey, nd.NewLitDB.GetPeerDB(), trackerURL, &ebus, nil) // TODO proxy/nat stuff
    64  	if err != nil {
    65  		return nil, err
    66  	}
    67  
    68  	// Actually start the thread to send messages.
    69  	nd.PeerMan.StartSending()
    70  
    71  	// Register adapter event handlers.  These are for hooking in the new peer management with the old one.
    72  	h1 := makeTmpNewPeerHandler(nd)
    73  	nd.Events.RegisterHandler("lnp2p.peer.new", h1)
    74  	h2 := makeTmpDisconnectPeerHandler(nd)
    75  	nd.Events.RegisterHandler("lnp2p.peer.disconnect", h2)
    76  
    77  	// Sets up handlers for all the messages we need to handle.
    78  	nd.registerHandlers()
    79  
    80  	var kg portxo.KeyGen
    81  	kg.Depth = 5
    82  	kg.Step[0] = 44 | 1<<31
    83  	kg.Step[1] = 513 | 1<<31
    84  	kg.Step[2] = 9 | 1<<31
    85  	kg.Step[3] = 0 | 1<<31
    86  	kg.Step[4] = 0 | 1<<31
    87  	nd.IdentityKey, err = kg.DerivePrivateKey(rootPrivKey)
    88  	if err != nil {
    89  		return nil, err
    90  	}
    91  
    92  	kg.Step[3] = 1 | 1<<31
    93  	rcPriv, err := kg.DerivePrivateKey(rootPrivKey)
    94  	nd.DefaultRemoteControlKey = rcPriv.PubKey()
    95  	rcPriv = nil
    96  
    97  	nd.TrackerURL = trackerURL
    98  
    99  	nd.ProxyURL = proxyURL
   100  
   101  	nd.Nat = nat
   102  
   103  	nd.InitRouting()
   104  
   105  	// optional tower activation
   106  
   107  	nd.Tower = new(watchtower.WatchTower)
   108  
   109  	// Create a new manager for the discreet log contracts
   110  	nd.DlcManager, err = dlc.NewManager(filepath.Join(nd.LitFolder, "dlc.db"))
   111  	if err != nil {
   112  		return nil, err
   113  	}
   114  
   115  	// make maps and channels
   116  	nd.UserMessageBox = make(chan string, 32)
   117  
   118  	nd.InProg = new(InFlightFund)
   119  	nd.InProg.done = make(chan uint32, 1)
   120  
   121  	nd.InProgDual = new(InFlightDualFund)
   122  	nd.InProgDual.done = make(chan *DualFundingResult, 1)
   123  
   124  	nd.InProgMultihop, err = nd.GetAllMultihopPayments()
   125  	if err != nil {
   126  		return nil, err
   127  	}
   128  
   129  	nd.RemoteMtx.Lock()
   130  	nd.RemoteCons = make(map[uint32]*RemotePeer)
   131  	nd.RemoteMtx.Unlock()
   132  
   133  	nd.SubWallet = make(map[uint32]UWallet)
   134  
   135  	// REFACTORING STUFF
   136  	nd.PeerMap = map[*lnp2p.Peer]*RemotePeer{}
   137  	nd.PeerMapMtx = &sync.Mutex{}
   138  
   139  	return nd, nil
   140  }
   141  
   142  // LinkBaseWallet activates a wallet and hooks it into the litnode.
   143  func (nd *LitNode) LinkBaseWallet(
   144  	privKey *[32]byte, birthHeight int32, resync bool, tower bool,
   145  	host string, proxy string, param *coinparam.Params) error {
   146  
   147  	rootpriv, err := hdkeychain.NewMaster(privKey[:], param)
   148  	if err != nil {
   149  		return err
   150  	}
   151  
   152  	WallitIdx := param.HDCoinType
   153  
   154  	// see if we've already attached a wallet for this coin type
   155  	if nd.SubWallet[WallitIdx] != nil {
   156  		return fmt.Errorf("coin type %d already linked", WallitIdx)
   157  	}
   158  	// see if startheight is below allowed with coinparam
   159  	if birthHeight < param.StartHeight {
   160  		return fmt.Errorf("%s birth height give as %d, but parameters start at %d",
   161  			param.Name, birthHeight, param.StartHeight)
   162  	}
   163  
   164  	// see if there are other wallets already linked
   165  	if len(nd.SubWallet) != 0 {
   166  		// there are; assert multiwallet (may already be asserted)
   167  		nd.MultiWallet = true
   168  	}
   169  
   170  	// if there aren't, Multiwallet will still be false; set new wallit to
   171  	// be the first & default
   172  	var cointype int
   173  	nd.SubWallet[WallitIdx], cointype, err = wallit.NewWallit(
   174  		rootpriv, birthHeight, resync, host, nd.LitFolder, proxy, param)
   175  
   176  	if err != nil {
   177  		logging.Error(err)
   178  		return err
   179  	}
   180  
   181  	if nd.ConnectedCoinTypes == nil {
   182  		nd.ConnectedCoinTypes = make(map[uint32]bool)
   183  		nd.ConnectedCoinTypes[uint32(cointype)] = true
   184  	}
   185  	nd.ConnectedCoinTypes[uint32(cointype)] = true
   186  	// re-register channel addresses
   187  	qChans, err := nd.GetAllQchans()
   188  	if err != nil {
   189  		return err
   190  	}
   191  
   192  	for _, qChan := range qChans {
   193  		var pkh [20]byte
   194  		pkhSlice := btcutil.Hash160(qChan.MyRefundPub[:])
   195  		copy(pkh[:], pkhSlice)
   196  		nd.SubWallet[WallitIdx].ExportHook().RegisterAddress(pkh)
   197  
   198  		logging.Infof("Registering outpoint %v", qChan.PorTxo.Op)
   199  
   200  		nd.SubWallet[WallitIdx].WatchThis(qChan.PorTxo.Op)
   201  	}
   202  
   203  	go nd.OPEventHandler(nd.SubWallet[WallitIdx].LetMeKnow())
   204  	go nd.HeightEventHandler(nd.SubWallet[WallitIdx].LetMeKnowHeight())
   205  
   206  	if !nd.MultiWallet {
   207  		nd.DefaultCoin = param.HDCoinType
   208  	}
   209  
   210  	// if this node is running a watchtower, link the watchtower to the
   211  	// new wallet block events
   212  
   213  	if tower {
   214  		err = nd.Tower.HookLink(
   215  			nd.LitFolder, param, nd.SubWallet[WallitIdx].ExportHook())
   216  		if err != nil {
   217  			return err
   218  		}
   219  	}
   220  
   221  	return nil
   222  }
   223  
   224  // Opens the DB file for the LnNode
   225  func (nd *LitNode) OpenDB(filename string) error {
   226  	var err error
   227  
   228  	nd.LitDB, err = bolt.Open(filename, 0644, nil)
   229  	if err != nil {
   230  		return err
   231  	}
   232  	// create buckets if they're not already there
   233  	err = nd.LitDB.Update(func(btx *bolt.Tx) error {
   234  		_, err := btx.CreateBucketIfNotExists(BKTChannelData)
   235  		if err != nil {
   236  			return err
   237  		}
   238  
   239  		_, err = btx.CreateBucketIfNotExists(BKTPeers)
   240  		if err != nil {
   241  			return err
   242  		}
   243  
   244  		_, err = btx.CreateBucketIfNotExists(BKTChanMap)
   245  		if err != nil {
   246  			return err
   247  		}
   248  		_, err = btx.CreateBucketIfNotExists(BKTPeerMap)
   249  		if err != nil {
   250  			return err
   251  		}
   252  
   253  		_, err = btx.CreateBucketIfNotExists(BKTWatch)
   254  		if err != nil {
   255  			return err
   256  		}
   257  
   258  		_, err = btx.CreateBucketIfNotExists(BKTHTLCOPs)
   259  		if err != nil {
   260  			return err
   261  		}
   262  
   263  		_, err = btx.CreateBucketIfNotExists(BKTPayments)
   264  		if err != nil {
   265  			return err
   266  		}
   267  
   268  		_, err = btx.CreateBucketIfNotExists(BKTRCAuth)
   269  		if err != nil {
   270  			return err
   271  		}
   272  
   273  		return nil
   274  	})
   275  	if err != nil {
   276  		return err
   277  	}
   278  	return nil
   279  }