lnwallet: once the reservation workflow is complete, wait then open the payment channel

* Hooks into the ChainNotifier infrastructure to receive a notification
once the funding transaction gets enough notifications.
* Still need to set up the notification grouting within a
LightningChannel to watch for uncooperative closures, and broadcasts
and revoked channel states.
This commit is contained in:
Olaoluwa Osuntokun 2016-01-06 16:17:18 -08:00
parent 6e0cfaf7ec
commit 07b0d5ca3e
3 changed files with 38 additions and 17 deletions

@ -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

@ -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

@ -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.