diff --git a/lnwallet/channel.go b/lnwallet/channel.go index 0171be09..f7f57f73 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -29,7 +29,7 @@ type PaymentHash [20]byte // TODO(roasbeef): future peer struct should embed this struct type LightningChannel struct { lnwallet *LightningWallet - channelEvents *chainntnfs.ChainNotifier + channelEvents chainntnfs.ChainNotifier // TODO(roasbeef): Stores all previous R values + timeouts for each // commitment update, plus some other meta-data...Or just use OP_RETURN @@ -39,7 +39,7 @@ type LightningChannel struct { // stateMtx protects concurrent access to the state struct. stateMtx sync.RWMutex - channelState channeldb.OpenChannel + channelState *channeldb.OpenChannel updateTotem chan struct{} @@ -61,8 +61,8 @@ type LightningChannel struct { } // newLightningChannel... -func newLightningChannel(wallet *LightningWallet, events *chainntnfs.ChainNotifier, - chanDB *channeldb.DB, state channeldb.OpenChannel) (*LightningChannel, error) { +func newLightningChannel(wallet *LightningWallet, events chainntnfs.ChainNotifier, + chanDB *channeldb.DB, state *channeldb.OpenChannel) (*LightningChannel, error) { lc := &LightningChannel{ lnwallet: wallet, @@ -74,6 +74,9 @@ func newLightningChannel(wallet *LightningWallet, events *chainntnfs.ChainNotifi unfufilledPayments: make(map[PaymentHash]*PaymentRequest), } + // TODO(roasbeef): do a NotifySpent for the funding input, and + // NotifyReceived for all commitment outputs. + // Populate the totem. lc.updateTotem <- struct{}{} @@ -318,7 +321,7 @@ func (lc *LightningChannel) AddHTLC(timeout uint32, value btcutil.Amount, // Re-create copies of the current commitment transactions to be updated. ourNewCommitTx, theirNewCommitTx, err := createNewCommitmentTxns( - lc.fundingTxIn, &lc.channelState, chanUpdate, amountToUs, amountToThem, + lc.fundingTxIn, lc.channelState, chanUpdate, amountToUs, amountToThem, ) if err != nil { return nil, err @@ -463,7 +466,7 @@ func (lc *LightningChannel) SettleHTLC(rValue [20]byte, newRevocation [20]byte) // Create new commitment transactions that reflect the settlement of // this pending HTLC. ourNewCommitTx, theirNewCommitTx, err := createNewCommitmentTxns( - lc.fundingTxIn, &lc.channelState, chanUpdate, amountToUs, amountToThem, + lc.fundingTxIn, lc.channelState, chanUpdate, amountToUs, amountToThem, ) if err != nil { return nil, err diff --git a/lnwallet/reservation.go b/lnwallet/reservation.go index 58052321..0df7b6ab 100644 --- a/lnwallet/reservation.go +++ b/lnwallet/reservation.go @@ -266,7 +266,7 @@ func (r *ChannelReservation) Cancel() error { // NOTE: If this method is called before .CompleteReservation(), it will block // indefinitely. func (r *ChannelReservation) WaitForChannelOpen() *LightningChannel { - return nil + return <-r.chanOpen } // * finish reset of tests diff --git a/lnwallet/wallet.go b/lnwallet/wallet.go index 80fa87be..0b708abd 100644 --- a/lnwallet/wallet.go +++ b/lnwallet/wallet.go @@ -323,6 +323,7 @@ func NewLightningWallet(config *Config) (*LightningWallet, walletdb.DB, error) { return nil, nil, err } + // TODO(roasbeef): logging return &LightningWallet{ db: db, chainNotifier: chainNotifier, @@ -967,19 +968,36 @@ func (l *LightningWallet) handleFundingCounterPartySigs(msg *addCounterPartySigs // which will be used for the lifetime of this channel. err = l.ChannelDB.PutOpenChannel(pendingReservation.partialState) - // TODO(roasbeef): broadcast now? - // * create goroutine, listens on blockconnected+blockdisconnected channels - // * after six blocks, then will create an LightningChannel struct and - // send over reservation. - // * will need a multi-plexer to fan out, to listen on ListenConnectedBlocks - // * should prob be a separate struct/modele - // * use NotifySpent in order to catch non-cooperative spends of revoked - // * NotifySpent(outpoints []*wire.OutPoint) - // commitment txns. Hmm using p2sh or bare multi-sig? - // * record partialState.CreationTime once tx is 'open' + // Create a goroutine to watch the chain so we can open the channel once + // the funding tx has enough confirmations. + // TODO(roasbeef): add number of confs to the confi + go l.openChannelAfterConfirmations(pendingReservation, 3) + msg.err <- err } +// openChannelAfterConfirmations creates, and opens a payment channel after +// the funding transaction created within the passed channel reservation +// obtains the specified number of confirmations. +func (l *LightningWallet) openChannelAfterConfirmations(res *ChannelReservation, numConfs uint32) { + // Register with the ChainNotifier for a notification once the funding + // transaction reaches `numConfs` confirmations. + trigger := &chainntnfs.NotificationTrigger{ + TriggerChan: make(chan struct{}, 1), + } + txid := res.partialState.FundingTx.TxSha() + l.chainNotifier.RegisterConfirmationsNotification(&txid, numConfs, trigger) + + // Wait until the specified number of confirmations has been reached. + <-trigger.TriggerChan + + // Finally, create and officially open the payment channel! + // TODO(roasbeef): CreationTime once tx is 'open' + channel, _ := newLightningChannel(l, l.chainNotifier, l.ChannelDB, + res.partialState) + res.chanOpen <- channel +} + // getNextRawKey retrieves the next key within our HD key-chain for use within // as a multi-sig key within the funding transaction, or within the commitment // transaction's outputs.