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 }