// NewLightningWallet creates/opens and initializes a LightningWallet instance. // If the wallet has never been created (according to the passed dataDir), first-time // setup is executed. // // NOTE: The passed channeldb, and ChainNotifier should already be fully // initialized/started before being passed as a function arugment. func NewLightningWallet(cdb *channeldb.DB, notifier chainntnfs.ChainNotifier, wallet WalletController, signer Signer, bio BlockChainIO, netParams *chaincfg.Params) (*LightningWallet, error) { // TODO(roasbeef): need a another wallet level config // Fetch the root derivation key from the wallet's HD chain. We'll use // this to generate specific Lightning related secrets on the fly. rootKey, err := wallet.FetchRootKey() if err != nil { return nil, err } // TODO(roasbeef): always re-derive on the fly? rootKeyRaw := rootKey.Serialize() rootMasterKey, err := hdkeychain.NewMaster(rootKeyRaw, netParams) if err != nil { return nil, err } return &LightningWallet{ rootKey: rootMasterKey, chainNotifier: notifier, Signer: signer, WalletController: wallet, chainIO: bio, ChannelDB: cdb, msgChan: make(chan interface{}, msgBufferSize), nextFundingID: 0, fundingLimbo: make(map[uint64]*ChannelReservation), lockedOutPoints: make(map[wire.OutPoint]struct{}), quit: make(chan struct{}), }, nil }
func TstCreateMasterKey(t *testing.T, seed []byte) *hdkeychain.ExtendedKey { key, err := hdkeychain.NewMaster(seed, &chaincfg.MainNetParams) if err != nil { t.Fatal(err) } return key }
// ReadKeyFileToECPriv returns an extendedkey from a file. // If there's no file there, it'll make one. If there's a password needed, // it'll prompt for one. One stop function. func ReadKeyFileToECPriv( filename string, p *chaincfg.Params) (*hdkeychain.ExtendedKey, error) { key32 := new([32]byte) _, err := os.Stat(filename) if err != nil { if os.IsNotExist(err) { // no key found, generate and save one fmt.Printf("No file %s, generating.\n", filename) rn, err := hdkeychain.GenerateSeed(32) if err != nil { return nil, err } copy(key32[:], rn[:]) err = SaveKeyToFileInteractive(filename, key32) if err != nil { return nil, err } } else { // unknown error, crash fmt.Printf("unknown\n") return nil, err } } key, err := LoadKeyFromFileInteractive(filename) if err != nil { return nil, err } rootpriv, err := hdkeychain.NewMaster(key[:], p) if err != nil { return nil, err } return rootpriv, nil }
// newMemWallet creates and returns a fully initialized instance of the // memWallet given a particular blockchain's parameters. func newMemWallet(net *chaincfg.Params, harnessID uint32) (*memWallet, error) { // The wallet's final HD seed is: hdSeed || harnessID. This method // ensures that each harness instance uses a deterministic root seed // based on its harness ID. var harnessHDSeed [chainhash.HashSize + 4]byte copy(harnessHDSeed[:], hdSeed[:]) binary.BigEndian.PutUint32(harnessHDSeed[:chainhash.HashSize], harnessID) hdRoot, err := hdkeychain.NewMaster(harnessHDSeed[:], net) if err != nil { return nil, nil } // The first child key from the hd root is reserved as the coinbase // generation address. coinbaseChild, err := hdRoot.Child(0) if err != nil { return nil, err } coinbaseKey, err := coinbaseChild.ECPrivKey() if err != nil { return nil, err } coinbaseAddr, err := keyToAddr(coinbaseKey, net) if err != nil { return nil, err } // Track the coinbase generation address to ensure we properly track // newly generated bitcoin we can spend. addrs := make(map[uint32]btcutil.Address) addrs[0] = coinbaseAddr return &memWallet{ net: net, coinbaseKey: coinbaseKey, coinbaseAddr: coinbaseAddr, hdIndex: 1, hdRoot: hdRoot, addrs: addrs, utxos: make(map[wire.OutPoint]*utxo), chainUpdateSignal: make(chan struct{}), reorgJournal: make(map[int32]*undoEntry), }, nil }