lnwallet: update the LightningChannel API usage for recent channels changes

This commit updates much of the state interaction within the
LightningChannel structure to account for the recent changes within the
chanenldb involving the OpenChannel struct, namely the introduction of
ChannelConfig and ChannelConstraints.
This commit is contained in:
Olaoluwa Osuntokun 2017-07-30 12:25:41 -07:00
parent b5044e9217
commit c7df82ab68
No known key found for this signature in database
GPG Key ID: 9CC5B105D03521A2

@ -571,13 +571,21 @@ func compactLogs(ourLog, theirLog *updateLog,
// //
// See the individual comments within the above methods for further details. // See the individual comments within the above methods for further details.
type LightningChannel struct { type LightningChannel struct {
signer Signer // signer is the main signer instances that will be responsible for
// signing any HTLC and commitment transaction generated by the state
// machine.
signer Signer
// signDesc is the primary sign descriptor that is capable of signing
// the commitment transaction that spends the multi-sig output.
signDesc *SignDescriptor signDesc *SignDescriptor
channelEvents chainntnfs.ChainNotifier channelEvents chainntnfs.ChainNotifier
sync.RWMutex // pendingACk denotes if we have an outstanding commitment transaction
// and are waiting for a revocation to be received. Until the
// revocation is received, we're unable to propose a new commitment
// state.
pendingACK bool pendingACK bool
status channelState status channelState
@ -589,6 +597,10 @@ type LightningChannel struct {
// Capcity is the total capacity of this channel. // Capcity is the total capacity of this channel.
Capacity btcutil.Amount Capacity btcutil.Amount
// stateHintObsfucator is a 48-bit state hint that's used to obfsucate
// the current state number on the commitment transactions.
stateHintObsfucator [StateHintSize]byte
// currentHeight is the current height of our local commitment chain. // currentHeight is the current height of our local commitment chain.
// This is also the same as the number of updates to the channel we've // This is also the same as the number of updates to the channel we've
// accepted. // accepted.
@ -629,6 +641,10 @@ type LightningChannel struct {
channelState *channeldb.OpenChannel channelState *channeldb.OpenChannel
localChanCfg *channeldb.ChannelConfig
remoteChanCfg *channeldb.ChannelConfig
// [local|remote]Log is a (mostly) append-only log storing all the HTLC // [local|remote]Log is a (mostly) append-only log storing all the HTLC
// updates to this channel. The log is walked backwards as HTLC updates // updates to this channel. The log is walked backwards as HTLC updates
// are applied in order to re-construct a commitment transaction from a // are applied in order to re-construct a commitment transaction from a
@ -654,9 +670,7 @@ type LightningChannel struct {
// way to lookup the original PaymentDescriptor. // way to lookup the original PaymentDescriptor.
rHashMap map[PaymentHash][]*PaymentDescriptor rHashMap map[PaymentHash][]*PaymentDescriptor
LocalDeliveryScript []byte
RemoteDeliveryScript []byte RemoteDeliveryScript []byte
// FundingWitnessScript is the witness script for the 2-of-2 multi-sig // FundingWitnessScript is the witness script for the 2-of-2 multi-sig
// that opened the channel. // that opened the channel.
FundingWitnessScript []byte FundingWitnessScript []byte
@ -697,6 +711,10 @@ type LightningChannel struct {
// might be processed by this channel at the specific point of time. // might be processed by this channel at the specific point of time.
availableLocalBalance btcutil.Amount availableLocalBalance btcutil.Amount
sync.RWMutex
wg sync.WaitGroup
shutdown int32 shutdown int32
quit chan struct{} quit chan struct{}
} }
@ -709,28 +727,48 @@ type LightningChannel struct {
func NewLightningChannel(signer Signer, events chainntnfs.ChainNotifier, func NewLightningChannel(signer Signer, events chainntnfs.ChainNotifier,
fe FeeEstimator, state *channeldb.OpenChannel) (*LightningChannel, error) { fe FeeEstimator, state *channeldb.OpenChannel) (*LightningChannel, error) {
localKey := state.LocalChanCfg.MultiSigKey.SerializeCompressed()
remoteKey := state.RemoteChanCfg.MultiSigKey.SerializeCompressed()
multiSigScript, err := genMultiSigScript(localKey, remoteKey)
if err != nil {
return nil, err
}
var stateHint [StateHintSize]byte
if state.IsInitiator {
stateHint = deriveStateHintObfuscator(
state.LocalChanCfg.PaymentBasePoint,
state.RemoteChanCfg.PaymentBasePoint,
)
} else {
stateHint = deriveStateHintObfuscator(
state.RemoteChanCfg.PaymentBasePoint,
state.LocalChanCfg.PaymentBasePoint,
)
}
lc := &LightningChannel{ lc := &LightningChannel{
signer: signer, signer: signer,
channelEvents: events, channelEvents: events,
feeEstimator: fe, feeEstimator: fe,
stateHintObsfucator: stateHint,
currentHeight: state.NumUpdates, currentHeight: state.NumUpdates,
remoteCommitChain: newCommitmentChain(state.NumUpdates), remoteCommitChain: newCommitmentChain(state.NumUpdates),
localCommitChain: newCommitmentChain(state.NumUpdates), localCommitChain: newCommitmentChain(state.NumUpdates),
channelState: state, channelState: state,
revocationWindowEdge: state.NumUpdates, localChanCfg: &state.LocalChanCfg,
remoteChanCfg: &state.RemoteChanCfg,
localUpdateLog: newUpdateLog(), localUpdateLog: newUpdateLog(),
remoteUpdateLog: newUpdateLog(), remoteUpdateLog: newUpdateLog(),
rHashMap: make(map[PaymentHash][]*PaymentDescriptor), rHashMap: make(map[PaymentHash][]*PaymentDescriptor),
Capacity: state.Capacity, Capacity: state.Capacity,
LocalDeliveryScript: state.OurDeliveryScript, FundingWitnessScript: multiSigScript,
RemoteDeliveryScript: state.TheirDeliveryScript,
FundingWitnessScript: state.FundingWitnessScript,
ForceCloseSignal: make(chan struct{}), ForceCloseSignal: make(chan struct{}),
UnilateralClose: make(chan *UnilateralCloseSummary, 1), UnilateralClose: make(chan *UnilateralCloseSummary, 1),
UnilateralCloseSignal: make(chan struct{}), UnilateralCloseSignal: make(chan struct{}),
ContractBreach: make(chan *BreachRetribution, 1), ContractBreach: make(chan *BreachRetribution, 1),
LocalFundingKey: state.OurMultiSigKey, LocalFundingKey: state.LocalChanCfg.MultiSigKey,
RemoteFundingKey: state.TheirMultiSigKey, RemoteFundingKey: state.RemoteChanCfg.MultiSigKey,
quit: make(chan struct{}), quit: make(chan struct{}),
} }
@ -738,15 +776,15 @@ func NewLightningChannel(signer Signer, events chainntnfs.ChainNotifier,
// for each side. // for each side.
lc.localCommitChain.addCommitment(&commitment{ lc.localCommitChain.addCommitment(&commitment{
height: lc.currentHeight, height: lc.currentHeight,
ourBalance: state.OurBalance, ourBalance: state.LocalBalance,
ourMessageIndex: 0, ourMessageIndex: 0,
theirBalance: state.TheirBalance, theirBalance: state.RemoteBalance,
theirMessageIndex: 0, theirMessageIndex: 0,
fee: state.CommitFee, fee: state.CommitFee,
feePerKw: state.FeePerKw, feePerKw: state.FeePerKw,
}) })
walletLog.Debugf("ChannelPoint(%v), starting local commitment: %v", walletLog.Debugf("ChannelPoint(%v), starting local commitment: %v",
state.ChanID, newLogClosure(func() string { state.FundingOutpoint, newLogClosure(func() string {
return spew.Sdump(lc.localCommitChain.tail()) return spew.Sdump(lc.localCommitChain.tail())
}), }),
) )
@ -760,9 +798,9 @@ func NewLightningChannel(signer Signer, events chainntnfs.ChainNotifier,
return nil, err return nil, err
} }
remoteCommitment := &commitment{ remoteCommitment := &commitment{
ourBalance: state.OurBalance, ourBalance: state.LocalBalance,
ourMessageIndex: 0, ourMessageIndex: 0,
theirBalance: state.TheirBalance, theirBalance: state.RemoteBalance,
theirMessageIndex: 0, theirMessageIndex: 0,
fee: state.CommitFee, fee: state.CommitFee,
feePerKw: state.FeePerKw, feePerKw: state.FeePerKw,
@ -774,7 +812,7 @@ func NewLightningChannel(signer Signer, events chainntnfs.ChainNotifier,
} }
lc.remoteCommitChain.addCommitment(remoteCommitment) lc.remoteCommitChain.addCommitment(remoteCommitment)
walletLog.Debugf("ChannelPoint(%v), starting remote commitment: %v", walletLog.Debugf("ChannelPoint(%v), starting remote commitment: %v",
state.ChanID, newLogClosure(func() string { state.FundingOutpoint, newLogClosure(func() string {
return spew.Sdump(lc.remoteCommitChain.tail()) return spew.Sdump(lc.remoteCommitChain.tail())
}), }),
) )
@ -788,15 +826,15 @@ func NewLightningChannel(signer Signer, events chainntnfs.ChainNotifier,
// Create the sign descriptor which we'll be using very frequently to // Create the sign descriptor which we'll be using very frequently to
// request a signature for the 2-of-2 multi-sig from the signer in // request a signature for the 2-of-2 multi-sig from the signer in
// order to complete channel state transitions. // order to complete channel state transitions.
fundingPkScript, err := witnessScriptHash(state.FundingWitnessScript) fundingPkScript, err := witnessScriptHash(multiSigScript)
if err != nil { if err != nil {
return nil, err return nil, err
} }
lc.fundingTxIn = wire.NewTxIn(state.FundingOutpoint, nil, nil) lc.fundingTxIn = wire.NewTxIn(&state.FundingOutpoint, nil, nil)
lc.fundingP2WSH = fundingPkScript lc.fundingP2WSH = fundingPkScript
lc.signDesc = &SignDescriptor{ lc.signDesc = &SignDescriptor{
PubKey: lc.channelState.OurMultiSigKey, PubKey: lc.localChanCfg.MultiSigKey,
WitnessScript: lc.channelState.FundingWitnessScript, WitnessScript: multiSigScript,
Output: &wire.TxOut{ Output: &wire.TxOut{
PkScript: lc.fundingP2WSH, PkScript: lc.fundingP2WSH,
Value: int64(lc.channelState.Capacity), Value: int64(lc.channelState.Capacity),
@ -833,6 +871,7 @@ func NewLightningChannel(signer Signer, events chainntnfs.ChainNotifier,
// Launch the close observer which will vigilantly watch the // Launch the close observer which will vigilantly watch the
// network for any broadcasts the current or prior commitment // network for any broadcasts the current or prior commitment
// transactions, taking action accordingly. // transactions, taking action accordingly.
lc.wg.Add(1)
go lc.closeObserver(channelCloseNtfn) go lc.closeObserver(channelCloseNtfn)
} }
@ -989,8 +1028,10 @@ func newBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64,
// //
// NOTE: This MUST be run as a goroutine. // NOTE: This MUST be run as a goroutine.
func (lc *LightningChannel) closeObserver(channelCloseNtfn *chainntnfs.SpendEvent) { func (lc *LightningChannel) closeObserver(channelCloseNtfn *chainntnfs.SpendEvent) {
defer lc.wg.Done()
walletLog.Infof("Close observer for ChannelPoint(%v) active", walletLog.Infof("Close observer for ChannelPoint(%v) active",
lc.channelState.ChanID) lc.channelState.FundingOutpoint)
var ( var (
commitSpend *chainntnfs.SpendDetail commitSpend *chainntnfs.SpendDetail
@ -1039,7 +1080,7 @@ func (lc *LightningChannel) closeObserver(channelCloseNtfn *chainntnfs.SpendEven
// If this is our commitment transaction, then we can exit here as we // If this is our commitment transaction, then we can exit here as we
// don't have any further processing we need to do (we can't cheat // don't have any further processing we need to do (we can't cheat
// ourselves :p). // ourselves :p).
commitmentHash := lc.channelState.OurCommitTx.TxHash() commitmentHash := lc.channelState.CommitTx.TxHash()
isOurCommitment := commitSpend.SpenderTxHash.IsEqual(&commitmentHash) isOurCommitment := commitSpend.SpenderTxHash.IsEqual(&commitmentHash)
if isOurCommitment { if isOurCommitment {
return return
@ -1047,7 +1088,7 @@ func (lc *LightningChannel) closeObserver(channelCloseNtfn *chainntnfs.SpendEven
// Decode the state hint encoded within the commitment transaction to // Decode the state hint encoded within the commitment transaction to
// determine if this is a revoked state or not. // determine if this is a revoked state or not.
obsfucator := lc.channelState.StateHintObsfucator obsfucator := lc.stateHintObsfucator
broadcastStateNum := GetStateNumHint(commitTxBroadcast, obsfucator) broadcastStateNum := GetStateNumHint(commitTxBroadcast, obsfucator)
currentStateNum := lc.currentHeight currentStateNum := lc.currentHeight
@ -1067,23 +1108,23 @@ func (lc *LightningChannel) closeObserver(channelCloseNtfn *chainntnfs.SpendEven
// their signature to us. // their signature to us.
case broadcastStateNum >= currentStateNum: case broadcastStateNum >= currentStateNum:
walletLog.Infof("Unilateral close of ChannelPoint(%v) "+ walletLog.Infof("Unilateral close of ChannelPoint(%v) "+
"detected", lc.channelState.ChanID) "detected", lc.channelState.FundingOutpoint)
// As we've detected that the channel has been closed, // As we've detected that the channel has been closed,
// immediately delete the state from disk, creating a close // immediately delete the state from disk, creating a close
// summary for future usage by related sub-systems. // summary for future usage by related sub-systems.
// TODO(roasbeef): include HTLC's // TODO(roasbeef): include HTLC's
// * and time-locked balance // * and time-locked balance, NEED TO???
closeSummary := &channeldb.ChannelCloseSummary{ closeSummary := channeldb.ChannelCloseSummary{
ChanPoint: *lc.channelState.ChanID, ChanPoint: lc.channelState.FundingOutpoint,
ClosingTXID: *commitSpend.SpenderTxHash, ClosingTXID: *commitSpend.SpenderTxHash,
RemotePub: lc.channelState.IdentityPub, RemotePub: lc.channelState.IdentityPub,
Capacity: lc.Capacity, Capacity: lc.Capacity,
SettledBalance: lc.channelState.OurBalance, SettledBalance: lc.channelState.LocalBalance,
CloseType: channeldb.ForceClose, CloseType: channeldb.ForceClose,
IsPending: true, IsPending: true,
} }
if err := lc.DeleteState(closeSummary); err != nil { if err := lc.DeleteState(&closeSummary); err != nil {
walletLog.Errorf("unable to delete channel state: %v", walletLog.Errorf("unable to delete channel state: %v",
err) err)
} }
@ -1104,7 +1145,7 @@ func (lc *LightningChannel) closeObserver(channelCloseNtfn *chainntnfs.SpendEven
case broadcastStateNum < currentStateNum: case broadcastStateNum < currentStateNum:
walletLog.Warnf("Remote peer has breached the channel "+ walletLog.Warnf("Remote peer has breached the channel "+
"contract for ChannelPoint(%v). Revoked state #%v was "+ "contract for ChannelPoint(%v). Revoked state #%v was "+
"broadcast!!!", lc.channelState.ChanID, "broadcast!!!", lc.channelState.FundingOutpoint,
broadcastStateNum) broadcastStateNum)
// Create a new reach retribution struct which contains all the // Create a new reach retribution struct which contains all the
@ -1455,7 +1496,7 @@ func (lc *LightningChannel) fetchCommitmentView(remoteChain bool,
// Set the state hint of the commitment transaction to facilitate // Set the state hint of the commitment transaction to facilitate
// quickly recovering the necessary penalty state in the case of an // quickly recovering the necessary penalty state in the case of an
// uncooperative broadcast. // uncooperative broadcast.
obsfucator := lc.channelState.StateHintObsfucator obsfucator := lc.stateHintObsfucator
stateNum := nextHeight stateNum := nextHeight
if err := SetStateNumHint(commitTx, stateNum, obsfucator); err != nil { if err := SetStateNumHint(commitTx, stateNum, obsfucator); err != nil {
return nil, err return nil, err
@ -1509,8 +1550,8 @@ func (lc *LightningChannel) evaluateHTLCView(view *htlcView, ourBalance,
skipThem := make(map[uint64]struct{}) skipThem := make(map[uint64]struct{})
// First we run through non-add entries in both logs, populating the // First we run through non-add entries in both logs, populating the
// skip sets and mutating the current chain state (crediting balances, etc) to // skip sets and mutating the current chain state (crediting balances,
// reflect the settle/timeout entry encountered. // etc) to reflect the settle/timeout entry encountered.
for _, entry := range view.ourUpdates { for _, entry := range view.ourUpdates {
if entry.EntryType == Add { if entry.EntryType == Add {
continue continue
@ -1552,8 +1593,8 @@ func (lc *LightningChannel) evaluateHTLCView(view *htlcView, ourBalance,
} }
// Next we take a second pass through all the log entries, skipping any // Next we take a second pass through all the log entries, skipping any
// settled HTLCs, and debiting the chain state balance due to any // settled HTLCs, and debiting the chain state balance due to any newly
// newly added HTLCs. // added HTLCs.
for _, entry := range view.ourUpdates { for _, entry := range view.ourUpdates {
isAdd := entry.EntryType == Add isAdd := entry.EntryType == Add
if _, ok := skipUs[entry.Index]; !isAdd || ok { if _, ok := skipUs[entry.Index]; !isAdd || ok {
@ -1719,13 +1760,16 @@ func (lc *LightningChannel) SignNextCommitment() ([]byte, error) {
} }
walletLog.Tracef("ChannelPoint(%v): extending remote chain to height %v", walletLog.Tracef("ChannelPoint(%v): extending remote chain to height %v",
lc.channelState.ChanID, newCommitView.height) lc.channelState.FundingOutpoint, newCommitView.height)
walletLog.Tracef("ChannelPoint(%v): remote chain: our_balance=%v, "+ walletLog.Tracef("ChannelPoint(%v): remote chain: our_balance=%v, "+
"their_balance=%v, commit_tx: %v", lc.channelState.ChanID, "their_balance=%v, commit_tx: %v",
newCommitView.ourBalance, newCommitView.theirBalance, lc.channelState.FundingOutpoint, newCommitView.ourBalance,
newCommitView.theirBalance,
newLogClosure(func() string { newLogClosure(func() string {
return spew.Sdump(newCommitView.txn) return spew.Sdump(newCommitView.txn)
})) }),
)
// Sign their version of the new commitment transaction. // Sign their version of the new commitment transaction.
lc.signDesc.SigHashes = txscript.NewTxSigHashes(newCommitView.txn) lc.signDesc.SigHashes = txscript.NewTxSigHashes(newCommitView.txn)
@ -1739,10 +1783,10 @@ func (lc *LightningChannel) SignNextCommitment() ([]byte, error) {
lc.remoteCommitChain.addCommitment(newCommitView) lc.remoteCommitChain.addCommitment(newCommitView)
// If we are the channel initiator then we would have signed any sent // If we are the channel initiator then we would have signed any sent
// fee update at this point, so mark this update as pending ACK, and set // fee update at this point, so mark this update as pending ACK, and
// pendingFeeUpdate to nil. We can do this since we know we won't sign // set pendingFeeUpdate to nil. We can do this since we know we won't
// any new commitment before receiving a revoke_and_ack, because of the // sign any new commitment before receiving a revoke_and_ack, because
// revocation window of 1. // of the revocation window of 1.
if lc.channelState.IsInitiator { if lc.channelState.IsInitiator {
lc.pendingAckFeeUpdate = lc.pendingFeeUpdate lc.pendingAckFeeUpdate = lc.pendingFeeUpdate
lc.pendingFeeUpdate = nil lc.pendingFeeUpdate = nil
@ -1879,10 +1923,10 @@ func (lc *LightningChannel) ReceiveNewCommitment(rawSig []byte) error {
} }
walletLog.Tracef("ChannelPoint(%v): extending local chain to height %v", walletLog.Tracef("ChannelPoint(%v): extending local chain to height %v",
lc.channelState.ChanID, localCommitmentView.height) lc.channelState.FundingOutpoint, localCommitmentView.height)
walletLog.Tracef("ChannelPoint(%v): local chain: our_balance=%v, "+ walletLog.Tracef("ChannelPoint(%v): local chain: our_balance=%v, "+
"their_balance=%v, commit_tx: %v", lc.channelState.ChanID, "their_balance=%v, commit_tx: %v", lc.channelState.FundingOutpoint,
localCommitmentView.ourBalance, localCommitmentView.theirBalance, localCommitmentView.ourBalance, localCommitmentView.theirBalance,
newLogClosure(func() string { newLogClosure(func() string {
return spew.Sdump(localCommitmentView.txn) return spew.Sdump(localCommitmentView.txn)
@ -1892,10 +1936,11 @@ func (lc *LightningChannel) ReceiveNewCommitment(rawSig []byte) error {
// Construct the sighash of the commitment transaction corresponding to // Construct the sighash of the commitment transaction corresponding to
// this newly proposed state update. // this newly proposed state update.
localCommitTx := localCommitmentView.txn localCommitTx := localCommitmentView.txn
multiSigScript := lc.channelState.FundingWitnessScript multiSigScript := lc.FundingWitnessScript
hashCache := txscript.NewTxSigHashes(localCommitTx) hashCache := txscript.NewTxSigHashes(localCommitTx)
sigHash, err := txscript.CalcWitnessSigHash(multiSigScript, hashCache, sigHash, err := txscript.CalcWitnessSigHash(multiSigScript, hashCache,
txscript.SigHashAll, localCommitTx, 0, int64(lc.channelState.Capacity)) txscript.SigHashAll, localCommitTx, 0,
int64(lc.channelState.Capacity))
if err != nil { if err != nil {
// TODO(roasbeef): fetchview has already mutated the HTLCs... // TODO(roasbeef): fetchview has already mutated the HTLCs...
// * need to either roll-back, or make pure // * need to either roll-back, or make pure
@ -2011,8 +2056,9 @@ func (lc *LightningChannel) RevokeCurrentCommitment() (*lnwire.RevokeAndAck, err
} }
walletLog.Tracef("ChannelPoint(%v): state transition accepted: "+ walletLog.Tracef("ChannelPoint(%v): state transition accepted: "+
"our_balance=%v, their_balance=%v", lc.channelState.ChanID, "our_balance=%v, their_balance=%v",
tail.ourBalance, tail.theirBalance) lc.channelState.FundingOutpoint, tail.ourBalance,
tail.theirBalance)
// In the process of revoking our current commitment, we've also // In the process of revoking our current commitment, we've also
// implicitly ACK'd their set of pending changes that arrived before // implicitly ACK'd their set of pending changes that arrived before
@ -2020,12 +2066,15 @@ func (lc *LightningChannel) RevokeCurrentCommitment() (*lnwire.RevokeAndAck, err
// ACK'd index within the log to right at this set of pending changes. // ACK'd index within the log to right at this set of pending changes.
lc.remoteUpdateLog.ackTransition() lc.remoteUpdateLog.ackTransition()
revocationMsg.ChanID = lnwire.NewChanIDFromOutPoint(lc.channelState.ChanID) revocationMsg.ChanID = lnwire.NewChanIDFromOutPoint(
&lc.channelState.FundingOutpoint,
)
return revocationMsg, nil return revocationMsg, nil
} }
// LocalAvailableBalance returns the amount of available money which might be // LocalAvailableBalance returns the amount of available money which might be
// procced by this channel at the specific point of time. // proceed by this channel at the specific point of time.
func (lc *LightningChannel) LocalAvailableBalance() btcutil.Amount { func (lc *LightningChannel) LocalAvailableBalance() btcutil.Amount {
lc.Lock() lc.Lock()
defer lc.Unlock() defer lc.Unlock()
@ -2096,7 +2145,7 @@ func (lc *LightningChannel) ReceiveRevocation(revMsg *lnwire.RevokeAndAck) ([]*P
lc.revocationWindow = append(lc.revocationWindow, revMsg) lc.revocationWindow = append(lc.revocationWindow, revMsg)
walletLog.Tracef("ChannelPoint(%v): remote party accepted state transition, "+ walletLog.Tracef("ChannelPoint(%v): remote party accepted state transition, "+
"revoked height %v, now at %v", lc.channelState.ChanID, "revoked height %v, now at %v", lc.channelState.FundingOutpoint,
lc.remoteCommitChain.tail().height, lc.remoteCommitChain.tail().height,
lc.remoteCommitChain.tail().height+1) lc.remoteCommitChain.tail().height+1)
@ -2220,9 +2269,6 @@ func (lc *LightningChannel) NextRevocationkey() (*btcec.PublicKey, error) {
// AddHTLC adds an HTLC to the state machine's local update log. This method // AddHTLC adds an HTLC to the state machine's local update log. This method
// should be called when preparing to send an outgoing HTLC. // should be called when preparing to send an outgoing HTLC.
//
// TODO(roasbeef): check for duplicates below? edge case during restart w/ HTLC
// persistence
func (lc *LightningChannel) AddHTLC(htlc *lnwire.UpdateAddHTLC) (uint64, error) { func (lc *LightningChannel) AddHTLC(htlc *lnwire.UpdateAddHTLC) (uint64, error) {
lc.Lock() lc.Lock()
defer lc.Unlock() defer lc.Unlock()
@ -2415,7 +2461,7 @@ func (lc *LightningChannel) ChannelPoint() *wire.OutPoint {
lc.RLock() lc.RLock()
defer lc.RUnlock() defer lc.RUnlock()
return lc.channelState.ChanID return &lc.channelState.FundingOutpoint
} }
// ShortChanID returns the short channel ID for the channel. The short channel // ShortChanID returns the short channel ID for the channel. The short channel
@ -2519,13 +2565,13 @@ func (lc *LightningChannel) addHTLC(commitTx *wire.MsgTx, ourCommit bool,
func (lc *LightningChannel) getSignedCommitTx() (*wire.MsgTx, error) { func (lc *LightningChannel) getSignedCommitTx() (*wire.MsgTx, error) {
// Fetch the current commitment transaction, along with their signature // Fetch the current commitment transaction, along with their signature
// for the transaction. // for the transaction.
commitTx := lc.channelState.OurCommitTx commitTx := lc.channelState.CommitTx
theirSig := append(lc.channelState.OurCommitSig, byte(txscript.SigHashAll)) theirSig := append(lc.channelState.CommitSig, byte(txscript.SigHashAll))
// With this, we then generate the full witness so the caller can // With this, we then generate the full witness so the caller can
// broadcast a fully signed transaction. // broadcast a fully signed transaction.
lc.signDesc.SigHashes = txscript.NewTxSigHashes(commitTx) lc.signDesc.SigHashes = txscript.NewTxSigHashes(&commitTx)
ourSigRaw, err := lc.signer.SignOutputRaw(commitTx, lc.signDesc) ourSigRaw, err := lc.signer.SignOutputRaw(&commitTx, lc.signDesc)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -2534,13 +2580,14 @@ func (lc *LightningChannel) getSignedCommitTx() (*wire.MsgTx, error) {
// With the final signature generated, create the witness stack // With the final signature generated, create the witness stack
// required to spend from the multi-sig output. // required to spend from the multi-sig output.
ourKey := lc.channelState.OurMultiSigKey.SerializeCompressed() ourKey := lc.localChanCfg.MultiSigKey.SerializeCompressed()
theirKey := lc.channelState.TheirMultiSigKey.SerializeCompressed() theirKey := lc.remoteChanCfg.MultiSigKey.SerializeCompressed()
commitTx.TxIn[0].Witness = SpendMultiSig(lc.FundingWitnessScript, ourKey, commitTx.TxIn[0].Witness = SpendMultiSig(lc.FundingWitnessScript, ourKey,
ourSig, theirKey, theirSig) ourSig, theirKey, theirSig)
return commitTx, nil return &commitTx, nil
}
} }
// ForceCloseSummary describes the final commitment state before the channel is // ForceCloseSummary describes the final commitment state before the channel is
@ -2656,7 +2703,7 @@ func (lc *LightningChannel) ForceClose() (*ForceCloseSummary, error) {
WitnessScript: selfScript, WitnessScript: selfScript,
Output: &wire.TxOut{ Output: &wire.TxOut{
PkScript: delayScript, PkScript: delayScript,
Value: int64(lc.channelState.OurBalance), Value: int64(lc.channelState.LocalBalance),
}, },
HashType: txscript.SigHashAll, HashType: txscript.SigHashAll,
} }
@ -2669,13 +2716,13 @@ func (lc *LightningChannel) ForceClose() (*ForceCloseSummary, error) {
close(lc.ForceCloseSignal) close(lc.ForceCloseSignal)
return &ForceCloseSummary{ return &ForceCloseSummary{
ChanPoint: *lc.channelState.ChanID, ChanPoint: lc.channelState.FundingOutpoint,
CloseTx: commitTx,
SelfOutpoint: wire.OutPoint{ SelfOutpoint: wire.OutPoint{
Hash: commitTx.TxHash(), Hash: commitTx.TxHash(),
Index: delayIndex, Index: delayIndex,
}, },
SelfOutputMaturity: csvTimeout, SelfOutputMaturity: csvTimeout,
CloseTx: commitTx,
SelfOutputSignDesc: selfSignDesc, SelfOutputSignDesc: selfSignDesc,
}, nil }, nil
} }
@ -2706,8 +2753,8 @@ func (lc *LightningChannel) CreateCloseProposal(feeRate uint64) ([]byte, uint64,
// not to persist the adjusted balance, as the feeRate may change // not to persist the adjusted balance, as the feeRate may change
// during the channel closing process. // during the channel closing process.
proposedFee := uint64(btcutil.Amount(feeRate) * commitWeight / 1000) proposedFee := uint64(btcutil.Amount(feeRate) * commitWeight / 1000)
ourBalance := lc.channelState.OurBalance ourBalance := lc.channelState.LocalBalance
theirBalance := lc.channelState.TheirBalance theirBalance := lc.channelState.RemoteBalance
if lc.channelState.IsInitiator { if lc.channelState.IsInitiator {
ourBalance = ourBalance - btcutil.Amount(proposedFee) ourBalance = ourBalance - btcutil.Amount(proposedFee)
@ -2716,9 +2763,9 @@ func (lc *LightningChannel) CreateCloseProposal(feeRate uint64) ([]byte, uint64,
} }
closeTx := CreateCooperativeCloseTx(lc.fundingTxIn, closeTx := CreateCooperativeCloseTx(lc.fundingTxIn,
lc.channelState.OurDustLimit, lc.channelState.TheirDustLimit, lc.localChanCfg.DustLimit, lc.remoteChanCfg.DustLimit,
ourBalance, theirBalance, lc.channelState.OurDeliveryScript, ourBalance, theirBalance, localDeliveryScript,
lc.channelState.TheirDeliveryScript, lc.channelState.IsInitiator) remoteDeliveryScript, lc.channelState.IsInitiator)
// Ensure that the transaction doesn't explicitly violate any // Ensure that the transaction doesn't explicitly violate any
// consensus rules such as being too big, or having any value with a // consensus rules such as being too big, or having any value with a
@ -2766,8 +2813,8 @@ func (lc *LightningChannel) CompleteCooperativeClose(localSig, remoteSig []byte,
// not to persist the adjusted balance, as the feeRate may change // not to persist the adjusted balance, as the feeRate may change
// during the channel closing process. // during the channel closing process.
proposedFee := uint64(btcutil.Amount(feeRate) * commitWeight / 1000) proposedFee := uint64(btcutil.Amount(feeRate) * commitWeight / 1000)
ourBalance := lc.channelState.OurBalance ourBalance := lc.channelState.LocalBalance
theirBalance := lc.channelState.TheirBalance theirBalance := lc.channelState.RemoteBalance
if lc.channelState.IsInitiator { if lc.channelState.IsInitiator {
ourBalance = ourBalance - btcutil.Amount(proposedFee) ourBalance = ourBalance - btcutil.Amount(proposedFee)
@ -2779,9 +2826,9 @@ func (lc *LightningChannel) CompleteCooperativeClose(localSig, remoteSig []byte,
// on this active channel back to both parties. In this current model, // on this active channel back to both parties. In this current model,
// the initiator pays full fees for the cooperative close transaction. // the initiator pays full fees for the cooperative close transaction.
closeTx := CreateCooperativeCloseTx(lc.fundingTxIn, closeTx := CreateCooperativeCloseTx(lc.fundingTxIn,
lc.channelState.OurDustLimit, lc.channelState.TheirDustLimit, lc.localChanCfg.DustLimit, lc.remoteChanCfg.DustLimit,
ourBalance, theirBalance, lc.channelState.OurDeliveryScript, ourBalance, theirBalance, localDeliveryScript,
lc.channelState.TheirDeliveryScript, lc.channelState.IsInitiator) remoteDeliveryScript, lc.channelState.IsInitiator)
// Ensure that the transaction doesn't explicitly validate any // Ensure that the transaction doesn't explicitly validate any
// consensus rules such as being too big, or having any value with a // consensus rules such as being too big, or having any value with a
@ -2794,8 +2841,8 @@ func (lc *LightningChannel) CompleteCooperativeClose(localSig, remoteSig []byte,
// Finally, construct the witness stack minding the order of the // Finally, construct the witness stack minding the order of the
// pubkeys+sigs on the stack. // pubkeys+sigs on the stack.
ourKey := lc.channelState.OurMultiSigKey.SerializeCompressed() ourKey := lc.localChanCfg.MultiSigKey.SerializeCompressed()
theirKey := lc.channelState.TheirMultiSigKey.SerializeCompressed() theirKey := lc.remoteChanCfg.MultiSigKey.SerializeCompressed()
witness := SpendMultiSig(lc.signDesc.WitnessScript, ourKey, witness := SpendMultiSig(lc.signDesc.WitnessScript, ourKey,
localSig, theirKey, remoteSig) localSig, theirKey, remoteSig)
closeTx.TxIn[0].Witness = witness closeTx.TxIn[0].Witness = witness
@ -2844,9 +2891,9 @@ func (lc *LightningChannel) UpdateFee(feePerKw btcutil.Amount) error {
defer lc.Unlock() defer lc.Unlock()
// Only initiator can send fee update, so trying to send one as // Only initiator can send fee update, so trying to send one as
// non-initiatior will fail. // non-initiator will fail.
if !lc.channelState.IsInitiator { if !lc.channelState.IsInitiator {
return fmt.Errorf("local fee update as non-initiatior") return fmt.Errorf("local fee update as non-initiator")
} }
lc.pendingFeeUpdate = &feePerKw lc.pendingFeeUpdate = &feePerKw
@ -2861,9 +2908,9 @@ func (lc *LightningChannel) ReceiveUpdateFee(feePerKw btcutil.Amount) error {
defer lc.Unlock() defer lc.Unlock()
// Only initiator can send fee update, and we must fail if we receive // Only initiator can send fee update, and we must fail if we receive
// fee update as initiatior // fee update as initiator
if lc.channelState.IsInitiator { if lc.channelState.IsInitiator {
return fmt.Errorf("received fee update as initiatior") return fmt.Errorf("received fee update as initiator")
} }
// TODO(halseth): should fail if fee update is unreasonable, // TODO(halseth): should fail if fee update is unreasonable,