From 877510745491960225c491209b4c7a1f46d8f4d3 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 5 Jul 2016 16:53:55 -0700 Subject: [PATCH] lnwallet: keep commitments cold at all times, store sig instead MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit changes prior behavior which stored a “hot” commitment transaction, meaning one which all the sigScript fully assembled and able to be broadcast. Instead, we now store the current signature for our commitment transaction as a separate field within the database and within memory. As a result, this eliminates a class of bugs which would erroneously broadcast a fully loaded commitment transaction, either leading to a loss of funds, or suspending availability to funds for a period of time. --- lnwallet/wallet.go | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/lnwallet/wallet.go b/lnwallet/wallet.go index 95582ab7..fb1f854f 100644 --- a/lnwallet/wallet.go +++ b/lnwallet/wallet.go @@ -853,7 +853,6 @@ func (l *LightningWallet) handleContributionMsg(req *addContributionMsg) { pendingReservation.partialState.ChanID = fundingOutpoint pendingReservation.partialState.TheirCommitKey = theirCommitKey pendingReservation.partialState.TheirMultiSigKey = theirContribution.MultiSigKey - pendingReservation.partialState.TheirCommitTx = theirCommitTx pendingReservation.partialState.OurCommitTx = ourCommitTx pendingReservation.ourContribution.RevocationKey = ourRevokeKey @@ -1050,7 +1049,6 @@ func (l *LightningWallet) handleFundingCounterPartySigs(msg *addCounterPartySigs // Finally, create an instance of a Script VM, and ensure that the // Script executes succesfully. - // TODO(roasbeef): remove afterwards, should *never* be hot... commitTx.TxIn[0].Witness = witness vm, err := txscript.NewEngine(p2wsh, commitTx, 0, txscript.StandardVerifyFlags, nil, @@ -1064,6 +1062,11 @@ func (l *LightningWallet) handleFundingCounterPartySigs(msg *addCounterPartySigs return } + // Strip and store the signature to ensure that our commitment + // transaction doesn't stay hot. + commitTx.TxIn[0].Witness = nil + pendingReservation.partialState.OurCommitSig = theirCommitSig + // Funding complete, this entry can be removed from limbo. l.limboMtx.Lock() delete(l.fundingLimbo, pendingReservation.reservationID) @@ -1147,7 +1150,6 @@ func (l *LightningWallet) handleSingleFunderSigs(req *addSingleFunderSigsMsg) { txsort.InPlaceSort(ourCommitTx) pendingReservation.partialState.OurCommitTx = ourCommitTx txsort.InPlaceSort(theirCommitTx) - pendingReservation.partialState.TheirCommitTx = theirCommitTx // Verify that their signature of valid for our current commitment // transaction. Re-generate both the redeemScript and p2sh output. We @@ -1184,7 +1186,8 @@ func (l *LightningWallet) handleSingleFunderSigs(req *addSingleFunderSigsMsg) { // Finally, create an instance of a Script VM, and ensure that the // Script executes succesfully. - ourCommitTx.TxIn[0].Witness = witness // TODO(roasbeef): don't stay hot!! + ourCommitTx.TxIn[0].Witness = witness + // TODO(roasbeef): replace engine with plain sighash check vm, err := txscript.NewEngine(p2wsh, ourCommitTx, 0, txscript.StandardVerifyFlags, nil, nil, channelValue) @@ -1197,6 +1200,11 @@ func (l *LightningWallet) handleSingleFunderSigs(req *addSingleFunderSigsMsg) { return } + // Strip and store the signature to ensure that our commitment + // transaction doesn't stay hot. + ourCommitTx.TxIn[0].Witness = nil + pendingReservation.partialState.OurCommitSig = req.theirCommitmentSig + // With their signature for our version of the commitment transactions // verified, we can now generate a signature for their version, // allowing the funding transaction to be safely broadcast.