lnwallet: support transactions and scripts for new commitment type

This commit modifies the channel state machine to be able to derive the
proper commitment and second-level HTLC output scripts required by the
new script-enforced leased channel commitment type.
This commit is contained in:
Wilmer Paulino
2021-07-14 17:16:13 -07:00
committed by Olaoluwa Osuntokun
parent 01e9bb2bff
commit 8cfb53f64a
11 changed files with 230 additions and 98 deletions

View File

@@ -2299,6 +2299,7 @@ func createInitChannels(revocationWindow int) (*lnwallet.LightningChannel, *lnwa
aliceCommitTx, bobCommitTx, err := lnwallet.CreateCommitmentTxns( aliceCommitTx, bobCommitTx, err := lnwallet.CreateCommitmentTxns(
channelBal, channelBal, &aliceCfg, &bobCfg, aliceCommitPoint, channelBal, channelBal, &aliceCfg, &bobCfg, aliceCommitPoint,
bobCommitPoint, *fundingTxIn, channeldb.SingleFunderTweaklessBit, bobCommitPoint, *fundingTxIn, channeldb.SingleFunderTweaklessBit,
false, 0,
) )
if err != nil { if err != nil {
return nil, nil, nil, err return nil, nil, nil, err

View File

@@ -362,8 +362,13 @@ func (c *chainWatcher) handleUnknownLocalState(
// With the keys derived, we'll construct the remote script that'll be // With the keys derived, we'll construct the remote script that'll be
// present if they have a non-dust balance on the commitment. // present if they have a non-dust balance on the commitment.
var leaseExpiry uint32
if c.cfg.chanState.ChanType.HasLeaseExpiration() {
leaseExpiry = c.cfg.chanState.ThawHeight
}
remoteScript, _, err := lnwallet.CommitScriptToRemote( remoteScript, _, err := lnwallet.CommitScriptToRemote(
c.cfg.chanState.ChanType, commitKeyRing.ToRemoteKey, c.cfg.chanState.ChanType, c.cfg.chanState.IsInitiator,
commitKeyRing.ToRemoteKey, leaseExpiry,
) )
if err != nil { if err != nil {
return false, err return false, err
@@ -373,8 +378,9 @@ func (c *chainWatcher) handleUnknownLocalState(
// the remote party allowing them to claim this output before the CSV // the remote party allowing them to claim this output before the CSV
// delay if we breach. // delay if we breach.
localScript, err := lnwallet.CommitScriptToSelf( localScript, err := lnwallet.CommitScriptToSelf(
c.cfg.chanState.ChanType, c.cfg.chanState.IsInitiator,
commitKeyRing.ToLocalKey, commitKeyRing.RevocationKey, commitKeyRing.ToLocalKey, commitKeyRing.RevocationKey,
uint32(c.cfg.chanState.LocalChanCfg.CsvDelay), uint32(c.cfg.chanState.LocalChanCfg.CsvDelay), leaseExpiry,
) )
if err != nil { if err != nil {
return false, err return false, err

View File

@@ -134,6 +134,7 @@ func createTestChannel(alicePrivKey, bobPrivKey []byte,
channelCapacity := aliceAmount + bobAmount channelCapacity := aliceAmount + bobAmount
csvTimeoutAlice := uint32(5) csvTimeoutAlice := uint32(5)
csvTimeoutBob := uint32(4) csvTimeoutBob := uint32(4)
isAliceInitiator := true
aliceConstraints := &channeldb.ChannelConstraints{ aliceConstraints := &channeldb.ChannelConstraints{
DustLimit: btcutil.Amount(200), DustLimit: btcutil.Amount(200),
@@ -230,6 +231,7 @@ func createTestChannel(alicePrivKey, bobPrivKey []byte,
aliceCommitTx, bobCommitTx, err := lnwallet.CreateCommitmentTxns( aliceCommitTx, bobCommitTx, err := lnwallet.CreateCommitmentTxns(
aliceAmount, bobAmount, &aliceCfg, &bobCfg, aliceCommitPoint, aliceAmount, bobAmount, &aliceCfg, &bobCfg, aliceCommitPoint,
bobCommitPoint, *fundingTxIn, channeldb.SingleFunderTweaklessBit, bobCommitPoint, *fundingTxIn, channeldb.SingleFunderTweaklessBit,
isAliceInitiator, 0,
) )
if err != nil { if err != nil {
return nil, nil, nil, err return nil, nil, nil, err
@@ -298,7 +300,7 @@ func createTestChannel(alicePrivKey, bobPrivKey []byte,
IdentityPub: aliceKeyPub, IdentityPub: aliceKeyPub,
FundingOutpoint: *prevOut, FundingOutpoint: *prevOut,
ChanType: channeldb.SingleFunderTweaklessBit, ChanType: channeldb.SingleFunderTweaklessBit,
IsInitiator: true, IsInitiator: isAliceInitiator,
Capacity: channelCapacity, Capacity: channelCapacity,
RemoteCurrentRevocation: bobCommitPoint, RemoteCurrentRevocation: bobCommitPoint,
RevocationProducer: alicePreimageProducer, RevocationProducer: alicePreimageProducer,
@@ -317,7 +319,7 @@ func createTestChannel(alicePrivKey, bobPrivKey []byte,
IdentityPub: bobKeyPub, IdentityPub: bobKeyPub,
FundingOutpoint: *prevOut, FundingOutpoint: *prevOut,
ChanType: channeldb.SingleFunderTweaklessBit, ChanType: channeldb.SingleFunderTweaklessBit,
IsInitiator: false, IsInitiator: !isAliceInitiator,
Capacity: channelCapacity, Capacity: channelCapacity,
RemoteCurrentRevocation: aliceCommitPoint, RemoteCurrentRevocation: aliceCommitPoint,
RevocationProducer: bobPreimageProducer, RevocationProducer: bobPreimageProducer,

View File

@@ -861,8 +861,8 @@ func TestWitnessSizes(t *testing.T) {
func genTimeoutTx(chanType channeldb.ChannelType) (*wire.MsgTx, error) { func genTimeoutTx(chanType channeldb.ChannelType) (*wire.MsgTx, error) {
// Create the unsigned timeout tx. // Create the unsigned timeout tx.
timeoutTx, err := lnwallet.CreateHtlcTimeoutTx( timeoutTx, err := lnwallet.CreateHtlcTimeoutTx(
chanType, testOutPoint, testAmt, testCLTVExpiry, chanType, false, testOutPoint, testAmt, testCLTVExpiry,
testCSVDelay, testPubkey, testPubkey, testCSVDelay, 0, testPubkey, testPubkey,
) )
if err != nil { if err != nil {
return nil, err return nil, err
@@ -903,7 +903,7 @@ func genTimeoutTx(chanType channeldb.ChannelType) (*wire.MsgTx, error) {
func genSuccessTx(chanType channeldb.ChannelType) (*wire.MsgTx, error) { func genSuccessTx(chanType channeldb.ChannelType) (*wire.MsgTx, error) {
// Create the unisgned success tx. // Create the unisgned success tx.
successTx, err := lnwallet.CreateHtlcSuccessTx( successTx, err := lnwallet.CreateHtlcSuccessTx(
chanType, testOutPoint, testAmt, testCSVDelay, chanType, false, testOutPoint, testAmt, testCSVDelay, 0,
testPubkey, testPubkey, testPubkey, testPubkey,
) )
if err != nil { if err != nil {

View File

@@ -2315,8 +2315,14 @@ func NewBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64,
// number so we can have the proper witness script to sign and include // number so we can have the proper witness script to sign and include
// within the final witness. // within the final witness.
theirDelay := uint32(chanState.RemoteChanCfg.CsvDelay) theirDelay := uint32(chanState.RemoteChanCfg.CsvDelay)
isRemoteInitiator := !chanState.IsInitiator
var leaseExpiry uint32
if chanState.ChanType.HasLeaseExpiration() {
leaseExpiry = chanState.ThawHeight
}
theirScript, err := CommitScriptToSelf( theirScript, err := CommitScriptToSelf(
keyRing.ToLocalKey, keyRing.RevocationKey, theirDelay, chanState.ChanType, isRemoteInitiator, keyRing.ToLocalKey,
keyRing.RevocationKey, theirDelay, leaseExpiry,
) )
if err != nil { if err != nil {
return nil, err return nil, err
@@ -2325,7 +2331,8 @@ func NewBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64,
// Since it is the remote breach we are reconstructing, the output going // Since it is the remote breach we are reconstructing, the output going
// to us will be a to-remote script with our local params. // to us will be a to-remote script with our local params.
ourScript, ourDelay, err := CommitScriptToRemote( ourScript, ourDelay, err := CommitScriptToRemote(
chanState.ChanType, keyRing.ToRemoteKey, chanState.ChanType, isRemoteInitiator, keyRing.ToRemoteKey,
leaseExpiry,
) )
if err != nil { if err != nil {
return nil, err return nil, err
@@ -2410,7 +2417,9 @@ func NewBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64,
// remote commitment transaction, and *they* go to the second // remote commitment transaction, and *they* go to the second
// level. // level.
secondLevelScript, err := SecondLevelHtlcScript( secondLevelScript, err := SecondLevelHtlcScript(
chanState.ChanType, isRemoteInitiator,
keyRing.RevocationKey, keyRing.ToLocalKey, theirDelay, keyRing.RevocationKey, keyRing.ToLocalKey, theirDelay,
leaseExpiry,
) )
if err != nil { if err != nil {
return nil, err return nil, err
@@ -2968,8 +2977,8 @@ func processFeeUpdate(feeUpdate *PaymentDescriptor, nextHeight uint64,
// signature can be submitted to the sigPool to generate all the signatures // signature can be submitted to the sigPool to generate all the signatures
// asynchronously and in parallel. // asynchronously and in parallel.
func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing, func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing,
chanType channeldb.ChannelType, chanType channeldb.ChannelType, isRemoteInitiator bool,
localChanCfg, remoteChanCfg *channeldb.ChannelConfig, leaseExpiry uint32, localChanCfg, remoteChanCfg *channeldb.ChannelConfig,
remoteCommitView *commitment) ([]SignJob, chan struct{}, error) { remoteCommitView *commitment) ([]SignJob, chan struct{}, error) {
txHash := remoteCommitView.txn.TxHash() txHash := remoteCommitView.txn.TxHash()
@@ -3019,9 +3028,9 @@ func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing,
Index: uint32(htlc.remoteOutputIndex), Index: uint32(htlc.remoteOutputIndex),
} }
sigJob.Tx, err = CreateHtlcTimeoutTx( sigJob.Tx, err = CreateHtlcTimeoutTx(
chanType, op, outputAmt, htlc.Timeout, chanType, isRemoteInitiator, op, outputAmt,
uint32(remoteChanCfg.CsvDelay), htlc.Timeout, uint32(remoteChanCfg.CsvDelay),
keyRing.RevocationKey, keyRing.ToLocalKey, leaseExpiry, keyRing.RevocationKey, keyRing.ToLocalKey,
) )
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
@@ -3072,7 +3081,8 @@ func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing,
Index: uint32(htlc.remoteOutputIndex), Index: uint32(htlc.remoteOutputIndex),
} }
sigJob.Tx, err = CreateHtlcSuccessTx( sigJob.Tx, err = CreateHtlcSuccessTx(
chanType, op, outputAmt, uint32(remoteChanCfg.CsvDelay), chanType, isRemoteInitiator, op, outputAmt,
uint32(remoteChanCfg.CsvDelay), leaseExpiry,
keyRing.RevocationKey, keyRing.ToLocalKey, keyRing.RevocationKey, keyRing.ToLocalKey,
) )
if err != nil { if err != nil {
@@ -3581,10 +3591,14 @@ func (lc *LightningChannel) SignNextCommitment() (lnwire.Sig, []lnwire.Sig, []ch
// need to generate signatures of each of them for the remote party's // need to generate signatures of each of them for the remote party's
// commitment state. We do so in two phases: first we generate and // commitment state. We do so in two phases: first we generate and
// submit the set of signature jobs to the worker pool. // submit the set of signature jobs to the worker pool.
var leaseExpiry uint32
if lc.channelState.ChanType.HasLeaseExpiration() {
leaseExpiry = lc.channelState.ThawHeight
}
sigBatch, cancelChan, err := genRemoteHtlcSigJobs( sigBatch, cancelChan, err := genRemoteHtlcSigJobs(
keyRing, lc.channelState.ChanType, keyRing, lc.channelState.ChanType, !lc.channelState.IsInitiator,
&lc.channelState.LocalChanCfg, &lc.channelState.RemoteChanCfg, leaseExpiry, &lc.channelState.LocalChanCfg,
newCommitView, &lc.channelState.RemoteChanCfg, newCommitView,
) )
if err != nil { if err != nil {
return sig, htlcSigs, nil, err return sig, htlcSigs, nil, err
@@ -4067,7 +4081,7 @@ func (lc *LightningChannel) computeView(view *htlcView, remoteChain bool,
// directly into the pool of workers. // directly into the pool of workers.
func genHtlcSigValidationJobs(localCommitmentView *commitment, func genHtlcSigValidationJobs(localCommitmentView *commitment,
keyRing *CommitmentKeyRing, htlcSigs []lnwire.Sig, keyRing *CommitmentKeyRing, htlcSigs []lnwire.Sig,
chanType channeldb.ChannelType, chanType channeldb.ChannelType, isLocalInitiator bool, leaseExpiry uint32,
localChanCfg, remoteChanCfg *channeldb.ChannelConfig) ([]VerifyJob, error) { localChanCfg, remoteChanCfg *channeldb.ChannelConfig) ([]VerifyJob, error) {
txHash := localCommitmentView.txn.TxHash() txHash := localCommitmentView.txn.TxHash()
@@ -4116,9 +4130,10 @@ func genHtlcSigValidationJobs(localCommitmentView *commitment,
outputAmt := htlc.Amount.ToSatoshis() - htlcFee outputAmt := htlc.Amount.ToSatoshis() - htlcFee
successTx, err := CreateHtlcSuccessTx( successTx, err := CreateHtlcSuccessTx(
chanType, op, outputAmt, chanType, isLocalInitiator, op,
uint32(localChanCfg.CsvDelay), outputAmt, uint32(localChanCfg.CsvDelay),
keyRing.RevocationKey, keyRing.ToLocalKey, leaseExpiry, keyRing.RevocationKey,
keyRing.ToLocalKey,
) )
if err != nil { if err != nil {
return nil, err return nil, err
@@ -4170,8 +4185,9 @@ func genHtlcSigValidationJobs(localCommitmentView *commitment,
outputAmt := htlc.Amount.ToSatoshis() - htlcFee outputAmt := htlc.Amount.ToSatoshis() - htlcFee
timeoutTx, err := CreateHtlcTimeoutTx( timeoutTx, err := CreateHtlcTimeoutTx(
chanType, op, outputAmt, htlc.Timeout, chanType, isLocalInitiator, op,
uint32(localChanCfg.CsvDelay), outputAmt, htlc.Timeout,
uint32(localChanCfg.CsvDelay), leaseExpiry,
keyRing.RevocationKey, keyRing.ToLocalKey, keyRing.RevocationKey, keyRing.ToLocalKey,
) )
if err != nil { if err != nil {
@@ -4385,9 +4401,14 @@ func (lc *LightningChannel) ReceiveNewCommitment(commitSig lnwire.Sig,
// As an optimization, we'll generate a series of jobs for the worker // As an optimization, we'll generate a series of jobs for the worker
// pool to verify each of the HTLc signatures presented. Once // pool to verify each of the HTLc signatures presented. Once
// generated, we'll submit these jobs to the worker pool. // generated, we'll submit these jobs to the worker pool.
var leaseExpiry uint32
if lc.channelState.ChanType.HasLeaseExpiration() {
leaseExpiry = lc.channelState.ThawHeight
}
verifyJobs, err := genHtlcSigValidationJobs( verifyJobs, err := genHtlcSigValidationJobs(
localCommitmentView, keyRing, htlcSigs, localCommitmentView, keyRing, htlcSigs,
lc.channelState.ChanType, &lc.channelState.LocalChanCfg, lc.channelState.ChanType, lc.channelState.IsInitiator,
leaseExpiry, &lc.channelState.LocalChanCfg,
&lc.channelState.RemoteChanCfg, &lc.channelState.RemoteChanCfg,
) )
if err != nil { if err != nil {
@@ -5570,18 +5591,24 @@ func NewUnilateralCloseSummary(chanState *channeldb.OpenChannel, signer input.Si
// First, we'll generate the commitment point and the revocation point // First, we'll generate the commitment point and the revocation point
// so we can re-construct the HTLC state and also our payment key. // so we can re-construct the HTLC state and also our payment key.
isOurCommit := false
keyRing := DeriveCommitmentKeys( keyRing := DeriveCommitmentKeys(
commitPoint, false, chanState.ChanType, commitPoint, isOurCommit, chanState.ChanType,
&chanState.LocalChanCfg, &chanState.RemoteChanCfg, &chanState.LocalChanCfg, &chanState.RemoteChanCfg,
) )
// Next, we'll obtain HTLC resolutions for all the outgoing HTLC's we // Next, we'll obtain HTLC resolutions for all the outgoing HTLC's we
// had on their commitment transaction. // had on their commitment transaction.
var leaseExpiry uint32
if chanState.ChanType.HasLeaseExpiration() {
leaseExpiry = chanState.ThawHeight
}
isRemoteInitiator := !chanState.IsInitiator
htlcResolutions, err := extractHtlcResolutions( htlcResolutions, err := extractHtlcResolutions(
chainfee.SatPerKWeight(remoteCommit.FeePerKw), false, signer, chainfee.SatPerKWeight(remoteCommit.FeePerKw), isOurCommit,
remoteCommit.Htlcs, keyRing, &chanState.LocalChanCfg, signer, remoteCommit.Htlcs, keyRing, &chanState.LocalChanCfg,
&chanState.RemoteChanCfg, commitSpend.SpendingTx, &chanState.RemoteChanCfg, commitSpend.SpendingTx,
chanState.ChanType, chanState.ChanType, isRemoteInitiator, leaseExpiry,
) )
if err != nil { if err != nil {
return nil, fmt.Errorf("unable to create htlc "+ return nil, fmt.Errorf("unable to create htlc "+
@@ -5594,7 +5621,8 @@ func NewUnilateralCloseSummary(chanState *channeldb.OpenChannel, signer input.Si
// locate the output index of our non-delayed output on the commitment // locate the output index of our non-delayed output on the commitment
// transaction. // transaction.
selfScript, maturityDelay, err := CommitScriptToRemote( selfScript, maturityDelay, err := CommitScriptToRemote(
chanState.ChanType, keyRing.ToRemoteKey, chanState.ChanType, isRemoteInitiator, keyRing.ToRemoteKey,
leaseExpiry,
) )
if err != nil { if err != nil {
return nil, fmt.Errorf("unable to create self commit "+ return nil, fmt.Errorf("unable to create self commit "+
@@ -5801,8 +5829,9 @@ type HtlcResolutions struct {
func newOutgoingHtlcResolution(signer input.Signer, func newOutgoingHtlcResolution(signer input.Signer,
localChanCfg *channeldb.ChannelConfig, commitTx *wire.MsgTx, localChanCfg *channeldb.ChannelConfig, commitTx *wire.MsgTx,
htlc *channeldb.HTLC, keyRing *CommitmentKeyRing, htlc *channeldb.HTLC, keyRing *CommitmentKeyRing,
feePerKw chainfee.SatPerKWeight, csvDelay uint32, feePerKw chainfee.SatPerKWeight, csvDelay, leaseExpiry uint32,
localCommit bool, chanType channeldb.ChannelType) (*OutgoingHtlcResolution, error) { localCommit, isCommitFromInitiator bool,
chanType channeldb.ChannelType) (*OutgoingHtlcResolution, error) {
op := wire.OutPoint{ op := wire.OutPoint{
Hash: commitTx.TxHash(), Hash: commitTx.TxHash(),
@@ -5854,8 +5883,9 @@ func newOutgoingHtlcResolution(signer input.Signer,
// With the fee calculated, re-construct the second level timeout // With the fee calculated, re-construct the second level timeout
// transaction. // transaction.
timeoutTx, err := CreateHtlcTimeoutTx( timeoutTx, err := CreateHtlcTimeoutTx(
chanType, op, secondLevelOutputAmt, htlc.RefundTimeout, chanType, isCommitFromInitiator, op, secondLevelOutputAmt,
csvDelay, keyRing.RevocationKey, keyRing.ToLocalKey, htlc.RefundTimeout, csvDelay, leaseExpiry, keyRing.RevocationKey,
keyRing.ToLocalKey,
) )
if err != nil { if err != nil {
return nil, err return nil, err
@@ -5901,7 +5931,8 @@ func newOutgoingHtlcResolution(signer input.Signer,
// transaction creates so we can generate the signDesc required to // transaction creates so we can generate the signDesc required to
// complete the claim process after a delay period. // complete the claim process after a delay period.
htlcSweepScript, err := SecondLevelHtlcScript( htlcSweepScript, err := SecondLevelHtlcScript(
keyRing.RevocationKey, keyRing.ToLocalKey, csvDelay, chanType, isCommitFromInitiator, keyRing.RevocationKey,
keyRing.ToLocalKey, csvDelay, leaseExpiry,
) )
if err != nil { if err != nil {
return nil, err return nil, err
@@ -5942,8 +5973,9 @@ func newOutgoingHtlcResolution(signer input.Signer,
func newIncomingHtlcResolution(signer input.Signer, func newIncomingHtlcResolution(signer input.Signer,
localChanCfg *channeldb.ChannelConfig, commitTx *wire.MsgTx, localChanCfg *channeldb.ChannelConfig, commitTx *wire.MsgTx,
htlc *channeldb.HTLC, keyRing *CommitmentKeyRing, htlc *channeldb.HTLC, keyRing *CommitmentKeyRing,
feePerKw chainfee.SatPerKWeight, csvDelay uint32, localCommit bool, feePerKw chainfee.SatPerKWeight, csvDelay, leaseExpiry uint32,
chanType channeldb.ChannelType) (*IncomingHtlcResolution, error) { localCommit, isCommitFromInitiator bool, chanType channeldb.ChannelType) (
*IncomingHtlcResolution, error) {
op := wire.OutPoint{ op := wire.OutPoint{
Hash: commitTx.TxHash(), Hash: commitTx.TxHash(),
@@ -5988,8 +6020,8 @@ func newIncomingHtlcResolution(signer input.Signer,
htlcFee := HtlcSuccessFee(chanType, feePerKw) htlcFee := HtlcSuccessFee(chanType, feePerKw)
secondLevelOutputAmt := htlc.Amt.ToSatoshis() - htlcFee secondLevelOutputAmt := htlc.Amt.ToSatoshis() - htlcFee
successTx, err := CreateHtlcSuccessTx( successTx, err := CreateHtlcSuccessTx(
chanType, op, secondLevelOutputAmt, csvDelay, chanType, isCommitFromInitiator, op, secondLevelOutputAmt,
keyRing.RevocationKey, keyRing.ToLocalKey, csvDelay, leaseExpiry, keyRing.RevocationKey, keyRing.ToLocalKey,
) )
if err != nil { if err != nil {
return nil, err return nil, err
@@ -6036,7 +6068,8 @@ func newIncomingHtlcResolution(signer input.Signer,
// creates so we can generate the proper signDesc to sweep it after the // creates so we can generate the proper signDesc to sweep it after the
// CSV delay has passed. // CSV delay has passed.
htlcSweepScript, err := SecondLevelHtlcScript( htlcSweepScript, err := SecondLevelHtlcScript(
keyRing.RevocationKey, keyRing.ToLocalKey, csvDelay, chanType, isCommitFromInitiator, keyRing.RevocationKey,
keyRing.ToLocalKey, csvDelay, leaseExpiry,
) )
if err != nil { if err != nil {
return nil, err return nil, err
@@ -6096,8 +6129,8 @@ func (r *OutgoingHtlcResolution) HtlcPoint() wire.OutPoint {
func extractHtlcResolutions(feePerKw chainfee.SatPerKWeight, ourCommit bool, func extractHtlcResolutions(feePerKw chainfee.SatPerKWeight, ourCommit bool,
signer input.Signer, htlcs []channeldb.HTLC, keyRing *CommitmentKeyRing, signer input.Signer, htlcs []channeldb.HTLC, keyRing *CommitmentKeyRing,
localChanCfg, remoteChanCfg *channeldb.ChannelConfig, localChanCfg, remoteChanCfg *channeldb.ChannelConfig,
commitTx *wire.MsgTx, chanType channeldb.ChannelType) ( commitTx *wire.MsgTx, chanType channeldb.ChannelType,
*HtlcResolutions, error) { isCommitFromInitiator bool, leaseExpiry uint32) (*HtlcResolutions, error) {
// TODO(roasbeef): don't need to swap csv delay? // TODO(roasbeef): don't need to swap csv delay?
dustLimit := remoteChanCfg.DustLimit dustLimit := remoteChanCfg.DustLimit
@@ -6129,8 +6162,8 @@ func extractHtlcResolutions(feePerKw chainfee.SatPerKWeight, ourCommit bool,
// as we can satisfy the contract. // as we can satisfy the contract.
ihr, err := newIncomingHtlcResolution( ihr, err := newIncomingHtlcResolution(
signer, localChanCfg, commitTx, &htlc, signer, localChanCfg, commitTx, &htlc,
keyRing, feePerKw, uint32(csvDelay), ourCommit, keyRing, feePerKw, uint32(csvDelay), leaseExpiry,
chanType, ourCommit, isCommitFromInitiator, chanType,
) )
if err != nil { if err != nil {
return nil, err return nil, err
@@ -6142,7 +6175,8 @@ func extractHtlcResolutions(feePerKw chainfee.SatPerKWeight, ourCommit bool,
ohr, err := newOutgoingHtlcResolution( ohr, err := newOutgoingHtlcResolution(
signer, localChanCfg, commitTx, &htlc, keyRing, signer, localChanCfg, commitTx, &htlc, keyRing,
feePerKw, uint32(csvDelay), ourCommit, chanType, feePerKw, uint32(csvDelay), leaseExpiry, ourCommit,
isCommitFromInitiator, chanType,
) )
if err != nil { if err != nil {
return nil, err return nil, err
@@ -6281,8 +6315,13 @@ func NewLocalForceCloseSummary(chanState *channeldb.OpenChannel,
&chanState.LocalChanCfg, &chanState.RemoteChanCfg, &chanState.LocalChanCfg, &chanState.RemoteChanCfg,
) )
var leaseExpiry uint32
if chanState.ChanType.HasLeaseExpiration() {
leaseExpiry = chanState.ThawHeight
}
toLocalScript, err := CommitScriptToSelf( toLocalScript, err := CommitScriptToSelf(
keyRing.ToLocalKey, keyRing.RevocationKey, csvTimeout, chanState.ChanType, chanState.IsInitiator, keyRing.ToLocalKey,
keyRing.RevocationKey, csvTimeout, leaseExpiry,
) )
if err != nil { if err != nil {
return nil, err return nil, err
@@ -6343,6 +6382,7 @@ func NewLocalForceCloseSummary(chanState *channeldb.OpenChannel,
chainfee.SatPerKWeight(localCommit.FeePerKw), true, signer, chainfee.SatPerKWeight(localCommit.FeePerKw), true, signer,
localCommit.Htlcs, keyRing, &chanState.LocalChanCfg, localCommit.Htlcs, keyRing, &chanState.LocalChanCfg,
&chanState.RemoteChanCfg, commitTx, chanState.ChanType, &chanState.RemoteChanCfg, commitTx, chanState.ChanType,
chanState.IsInitiator, leaseExpiry,
) )
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -192,14 +192,31 @@ type ScriptInfo struct {
// CommitScriptToSelf constructs the public key script for the output on the // CommitScriptToSelf constructs the public key script for the output on the
// commitment transaction paying to the "owner" of said commitment transaction. // commitment transaction paying to the "owner" of said commitment transaction.
// If the other party learns of the preimage to the revocation hash, then they // The `initiator` argument should correspond to the owner of the commitment
// can claim all the settled funds in the channel, plus the unsettled funds. // tranasction which we are generating the to_local script for. If the other
func CommitScriptToSelf(selfKey, revokeKey *btcec.PublicKey, csvDelay uint32) ( // party learns of the preimage to the revocation hash, then they can claim all
// the settled funds in the channel, plus the unsettled funds.
func CommitScriptToSelf(chanType channeldb.ChannelType, initiator bool,
selfKey, revokeKey *btcec.PublicKey, csvDelay, leaseExpiry uint32) (
*ScriptInfo, error) { *ScriptInfo, error) {
toLocalRedeemScript, err := input.CommitScriptToSelf( var (
csvDelay, selfKey, revokeKey, toLocalRedeemScript []byte
err error
) )
switch {
// If we are the initiator of a leased channel, then we have an
// additional CLTV requirement in addition to the usual CSV requirement.
case initiator && chanType.HasLeaseExpiration():
toLocalRedeemScript, err = input.LeaseCommitScriptToSelf(
selfKey, revokeKey, csvDelay, leaseExpiry,
)
default:
toLocalRedeemScript, err = input.CommitScriptToSelf(
csvDelay, selfKey, revokeKey,
)
}
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -216,14 +233,38 @@ func CommitScriptToSelf(selfKey, revokeKey *btcec.PublicKey, csvDelay uint32) (
} }
// CommitScriptToRemote derives the appropriate to_remote script based on the // CommitScriptToRemote derives the appropriate to_remote script based on the
// channel's commitment type. The second return value is the CSV delay of the // channel's commitment type. The `initiator` argument should correspond to the
// output script, what must be satisfied in order to spend the output. // owner of the commitment tranasction which we are generating the to_remote
func CommitScriptToRemote(chanType channeldb.ChannelType, // script for. The second return value is the CSV delay of the output script,
key *btcec.PublicKey) (*ScriptInfo, uint32, error) { // what must be satisfied in order to spend the output.
func CommitScriptToRemote(chanType channeldb.ChannelType, initiator bool,
key *btcec.PublicKey, leaseExpiry uint32) (*ScriptInfo, uint32, error) {
switch {
// If we are not the initiator of a leased channel, then the remote
// party has an additional CLTV requirement in addition to the 1 block
// CSV requirement.
case chanType.HasLeaseExpiration() && !initiator:
script, err := input.LeaseCommitScriptToRemoteConfirmed(
key, leaseExpiry,
)
if err != nil {
return nil, 0, err
}
p2wsh, err := input.WitnessScriptHash(script)
if err != nil {
return nil, 0, err
}
return &ScriptInfo{
PkScript: p2wsh,
WitnessScript: script,
}, 1, nil
// If this channel type has anchors, we derive the delayed to_remote // If this channel type has anchors, we derive the delayed to_remote
// script. // script.
if chanType.HasAnchors() { case chanType.HasAnchors():
script, err := input.CommitScriptToRemoteConfirmed(key) script, err := input.CommitScriptToRemoteConfirmed(key)
if err != nil { if err != nil {
return nil, 0, err return nil, 0, err
@@ -238,20 +279,22 @@ func CommitScriptToRemote(chanType channeldb.ChannelType,
PkScript: p2wsh, PkScript: p2wsh,
WitnessScript: script, WitnessScript: script,
}, 1, nil }, 1, nil
}
// Otherwise the to_remote will be a simple p2wkh. default:
p2wkh, err := input.CommitScriptUnencumbered(key) // Otherwise the to_remote will be a simple p2wkh.
if err != nil { p2wkh, err := input.CommitScriptUnencumbered(key)
return nil, 0, err if err != nil {
} return nil, 0, err
}
// Since this is a regular P2WKH, the WitnessScipt and PkScript should // Since this is a regular P2WKH, the WitnessScipt and PkScript
// both be set to the script hash. // should both be set to the script hash.
return &ScriptInfo{ return &ScriptInfo{
WitnessScript: p2wkh, WitnessScript: p2wkh,
PkScript: p2wkh, PkScript: p2wkh,
}, 0, nil }, 0, nil
}
} }
// HtlcSigHashType returns the sighash type to use for HTLC success and timeout // HtlcSigHashType returns the sighash type to use for HTLC success and timeout
@@ -296,13 +339,30 @@ func HtlcSecondLevelInputSequence(chanType channeldb.ChannelType) uint32 {
// on the channel's commitment type. It is the uniform script that's used as the // on the channel's commitment type. It is the uniform script that's used as the
// output for the second-level HTLC transactions. The second level transaction // output for the second-level HTLC transactions. The second level transaction
// act as a sort of covenant, ensuring that a 2-of-2 multi-sig output can only // act as a sort of covenant, ensuring that a 2-of-2 multi-sig output can only
// be spent in a particular way, and to a particular output. // be spent in a particular way, and to a particular output. The `initiator`
func SecondLevelHtlcScript(revocationKey, delayKey *btcec.PublicKey, // argument should correspond to the owner of the commitment tranasction which
csvDelay uint32) (*ScriptInfo, error) { // we are generating the to_local script for.
func SecondLevelHtlcScript(chanType channeldb.ChannelType, initiator bool,
revocationKey, delayKey *btcec.PublicKey,
csvDelay, leaseExpiry uint32) (*ScriptInfo, error) {
witnessScript, err := input.SecondLevelHtlcScript( var (
revocationKey, delayKey, csvDelay, witnessScript []byte
err error
) )
switch {
// If we are the initiator of a leased channel, then we have an
// additional CLTV requirement in addition to the usual CSV requirement.
case initiator && chanType.HasLeaseExpiration():
witnessScript, err = input.LeaseSecondLevelHtlcScript(
revocationKey, delayKey, csvDelay, leaseExpiry,
)
default:
witnessScript, err = input.SecondLevelHtlcScript(
revocationKey, delayKey, csvDelay,
)
}
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -549,19 +609,23 @@ func (cb *CommitmentBuilder) createUnsignedCommitmentTx(ourBalance,
// CreateCommitTx with parameters matching the perspective, to generate // CreateCommitTx with parameters matching the perspective, to generate
// a new commitment transaction with all the latest unsettled/un-timed // a new commitment transaction with all the latest unsettled/un-timed
// out HTLCs. // out HTLCs.
var leaseExpiry uint32
if cb.chanState.ChanType.HasLeaseExpiration() {
leaseExpiry = cb.chanState.ThawHeight
}
if isOurs { if isOurs {
commitTx, err = CreateCommitTx( commitTx, err = CreateCommitTx(
cb.chanState.ChanType, fundingTxIn(cb.chanState), keyRing, cb.chanState.ChanType, fundingTxIn(cb.chanState), keyRing,
&cb.chanState.LocalChanCfg, &cb.chanState.RemoteChanCfg, &cb.chanState.LocalChanCfg, &cb.chanState.RemoteChanCfg,
ourBalance.ToSatoshis(), theirBalance.ToSatoshis(), ourBalance.ToSatoshis(), theirBalance.ToSatoshis(),
numHTLCs, numHTLCs, cb.chanState.IsInitiator, leaseExpiry,
) )
} else { } else {
commitTx, err = CreateCommitTx( commitTx, err = CreateCommitTx(
cb.chanState.ChanType, fundingTxIn(cb.chanState), keyRing, cb.chanState.ChanType, fundingTxIn(cb.chanState), keyRing,
&cb.chanState.RemoteChanCfg, &cb.chanState.LocalChanCfg, &cb.chanState.RemoteChanCfg, &cb.chanState.LocalChanCfg,
theirBalance.ToSatoshis(), ourBalance.ToSatoshis(), theirBalance.ToSatoshis(), ourBalance.ToSatoshis(),
numHTLCs, numHTLCs, !cb.chanState.IsInitiator, leaseExpiry,
) )
} }
if err != nil { if err != nil {
@@ -660,12 +724,13 @@ func (cb *CommitmentBuilder) createUnsignedCommitmentTx(ourBalance,
// output paying to the "owner" of the commitment transaction which can be // output paying to the "owner" of the commitment transaction which can be
// spent after a relative block delay or revocation event, and a remote output // spent after a relative block delay or revocation event, and a remote output
// paying the counterparty within the channel, which can be spent immediately // paying the counterparty within the channel, which can be spent immediately
// or after a delay depending on the commitment type.. // or after a delay depending on the commitment type. The `initiator` argument
// should correspond to the owner of the commitment tranasction we are creating.
func CreateCommitTx(chanType channeldb.ChannelType, func CreateCommitTx(chanType channeldb.ChannelType,
fundingOutput wire.TxIn, keyRing *CommitmentKeyRing, fundingOutput wire.TxIn, keyRing *CommitmentKeyRing,
localChanCfg, remoteChanCfg *channeldb.ChannelConfig, localChanCfg, remoteChanCfg *channeldb.ChannelConfig,
amountToLocal, amountToRemote btcutil.Amount, amountToLocal, amountToRemote btcutil.Amount,
numHTLCs int64) (*wire.MsgTx, error) { numHTLCs int64, initiator bool, leaseExpiry uint32) (*wire.MsgTx, error) {
// First, we create the script for the delayed "pay-to-self" output. // First, we create the script for the delayed "pay-to-self" output.
// This output has 2 main redemption clauses: either we can redeem the // This output has 2 main redemption clauses: either we can redeem the
@@ -673,8 +738,8 @@ func CreateCommitTx(chanType channeldb.ChannelType,
// the funds with the revocation key if we broadcast a revoked // the funds with the revocation key if we broadcast a revoked
// commitment transaction. // commitment transaction.
toLocalScript, err := CommitScriptToSelf( toLocalScript, err := CommitScriptToSelf(
keyRing.ToLocalKey, keyRing.RevocationKey, chanType, initiator, keyRing.ToLocalKey, keyRing.RevocationKey,
uint32(localChanCfg.CsvDelay), uint32(localChanCfg.CsvDelay), leaseExpiry,
) )
if err != nil { if err != nil {
return nil, err return nil, err
@@ -682,7 +747,7 @@ func CreateCommitTx(chanType channeldb.ChannelType,
// Next, we create the script paying to the remote. // Next, we create the script paying to the remote.
toRemoteScript, _, err := CommitScriptToRemote( toRemoteScript, _, err := CommitScriptToRemote(
chanType, keyRing.ToRemoteKey, chanType, initiator, keyRing.ToRemoteKey, leaseExpiry,
) )
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -119,6 +119,7 @@ func CreateTestChannels(chanType channeldb.ChannelType) (
channelBal := channelCapacity / 2 channelBal := channelCapacity / 2
csvTimeoutAlice := uint32(5) csvTimeoutAlice := uint32(5)
csvTimeoutBob := uint32(4) csvTimeoutBob := uint32(4)
isAliceInitiator := true
prevOut := &wire.OutPoint{ prevOut := &wire.OutPoint{
Hash: chainhash.Hash(testHdSeed), Hash: chainhash.Hash(testHdSeed),
@@ -223,7 +224,7 @@ func CreateTestChannels(chanType channeldb.ChannelType) (
aliceCommitTx, bobCommitTx, err := CreateCommitmentTxns( aliceCommitTx, bobCommitTx, err := CreateCommitmentTxns(
channelBal, channelBal, &aliceCfg, &bobCfg, aliceCommitPoint, channelBal, channelBal, &aliceCfg, &bobCfg, aliceCommitPoint,
bobCommitPoint, *fundingTxIn, chanType, bobCommitPoint, *fundingTxIn, chanType, isAliceInitiator, 0,
) )
if err != nil { if err != nil {
return nil, nil, nil, err return nil, nil, nil, err
@@ -318,7 +319,7 @@ func CreateTestChannels(chanType channeldb.ChannelType) (
FundingOutpoint: *prevOut, FundingOutpoint: *prevOut,
ShortChannelID: shortChanID, ShortChannelID: shortChanID,
ChanType: chanType, ChanType: chanType,
IsInitiator: true, IsInitiator: isAliceInitiator,
Capacity: channelCapacity, Capacity: channelCapacity,
RemoteCurrentRevocation: bobCommitPoint, RemoteCurrentRevocation: bobCommitPoint,
RevocationProducer: alicePreimageProducer, RevocationProducer: alicePreimageProducer,
@@ -336,7 +337,7 @@ func CreateTestChannels(chanType channeldb.ChannelType) (
FundingOutpoint: *prevOut, FundingOutpoint: *prevOut,
ShortChannelID: shortChanID, ShortChannelID: shortChanID,
ChanType: chanType, ChanType: chanType,
IsInitiator: false, IsInitiator: !isAliceInitiator,
Capacity: channelCapacity, Capacity: channelCapacity,
RemoteCurrentRevocation: aliceCommitPoint, RemoteCurrentRevocation: aliceCommitPoint,
RevocationProducer: bobPreimageProducer, RevocationProducer: bobPreimageProducer,

View File

@@ -44,9 +44,10 @@ var (
// In order to spend the HTLC output, the witness for the passed transaction // In order to spend the HTLC output, the witness for the passed transaction
// should be: // should be:
// * <0> <sender sig> <recvr sig> <preimage> // * <0> <sender sig> <recvr sig> <preimage>
func CreateHtlcSuccessTx(chanType channeldb.ChannelType, func CreateHtlcSuccessTx(chanType channeldb.ChannelType, initiator bool,
htlcOutput wire.OutPoint, htlcAmt btcutil.Amount, csvDelay uint32, htlcOutput wire.OutPoint, htlcAmt btcutil.Amount, csvDelay,
revocationKey, delayKey *btcec.PublicKey) (*wire.MsgTx, error) { leaseExpiry uint32, revocationKey, delayKey *btcec.PublicKey) (
*wire.MsgTx, error) {
// Create a version two transaction (as the success version of this // Create a version two transaction (as the success version of this
// spends an output with a CSV timeout). // spends an output with a CSV timeout).
@@ -65,7 +66,8 @@ func CreateHtlcSuccessTx(chanType channeldb.ChannelType,
// level HTLC which forces a covenant w.r.t what can be done with all // level HTLC which forces a covenant w.r.t what can be done with all
// HTLC outputs. // HTLC outputs.
script, err := SecondLevelHtlcScript( script, err := SecondLevelHtlcScript(
revocationKey, delayKey, csvDelay, chanType, initiator, revocationKey, delayKey, csvDelay,
leaseExpiry,
) )
if err != nil { if err != nil {
return nil, err return nil, err
@@ -97,9 +99,9 @@ func CreateHtlcSuccessTx(chanType channeldb.ChannelType,
// NOTE: The passed amount for the HTLC should take into account the required // NOTE: The passed amount for the HTLC should take into account the required
// fee rate at the time the HTLC was created. The fee should be able to // fee rate at the time the HTLC was created. The fee should be able to
// entirely pay for this (tiny: 1-in 1-out) transaction. // entirely pay for this (tiny: 1-in 1-out) transaction.
func CreateHtlcTimeoutTx(chanType channeldb.ChannelType, func CreateHtlcTimeoutTx(chanType channeldb.ChannelType, initiator bool,
htlcOutput wire.OutPoint, htlcAmt btcutil.Amount, htlcOutput wire.OutPoint, htlcAmt btcutil.Amount,
cltvExpiry, csvDelay uint32, cltvExpiry, csvDelay, leaseExpiry uint32,
revocationKey, delayKey *btcec.PublicKey) (*wire.MsgTx, error) { revocationKey, delayKey *btcec.PublicKey) (*wire.MsgTx, error) {
// Create a version two transaction (as the success version of this // Create a version two transaction (as the success version of this
@@ -123,7 +125,8 @@ func CreateHtlcTimeoutTx(chanType channeldb.ChannelType,
// level HTLC which forces a covenant w.r.t what can be done with all // level HTLC which forces a covenant w.r.t what can be done with all
// HTLC outputs. // HTLC outputs.
script, err := SecondLevelHtlcScript( script, err := SecondLevelHtlcScript(
revocationKey, delayKey, csvDelay, chanType, initiator, revocationKey, delayKey, csvDelay,
leaseExpiry,
) )
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -573,7 +573,7 @@ func testSpendValidation(t *testing.T, tweakless bool) {
} }
commitmentTx, err := CreateCommitTx( commitmentTx, err := CreateCommitTx(
channelType, *fakeFundingTxIn, keyRing, aliceChanCfg, channelType, *fakeFundingTxIn, keyRing, aliceChanCfg,
bobChanCfg, channelBalance, channelBalance, 0, bobChanCfg, channelBalance, channelBalance, 0, true, 0,
) )
if err != nil { if err != nil {
t.Fatalf("unable to create commitment transaction: %v", nil) t.Fatalf("unable to create commitment transaction: %v", nil)
@@ -889,7 +889,7 @@ func createTestChannelsForVectors(tc *testContext, chanType channeldb.ChannelTyp
remoteCommitTx, localCommitTx, err := CreateCommitmentTxns( remoteCommitTx, localCommitTx, err := CreateCommitmentTxns(
remoteBalance, localBalance-commitFee, remoteBalance, localBalance-commitFee,
&remoteCfg, &localCfg, remoteCommitPoint, &remoteCfg, &localCfg, remoteCommitPoint,
localCommitPoint, *fundingTxIn, chanType, localCommitPoint, *fundingTxIn, chanType, true, 0,
) )
require.NoError(t, err) require.NoError(t, err)

View File

@@ -1246,8 +1246,8 @@ func (l *LightningWallet) handleFundingCancelRequest(req *fundingReserveCancelMs
func CreateCommitmentTxns(localBalance, remoteBalance btcutil.Amount, func CreateCommitmentTxns(localBalance, remoteBalance btcutil.Amount,
ourChanCfg, theirChanCfg *channeldb.ChannelConfig, ourChanCfg, theirChanCfg *channeldb.ChannelConfig,
localCommitPoint, remoteCommitPoint *btcec.PublicKey, localCommitPoint, remoteCommitPoint *btcec.PublicKey,
fundingTxIn wire.TxIn, chanType channeldb.ChannelType) ( fundingTxIn wire.TxIn, chanType channeldb.ChannelType, initiator bool,
*wire.MsgTx, *wire.MsgTx, error) { leaseExpiry uint32) (*wire.MsgTx, *wire.MsgTx, error) {
localCommitmentKeys := DeriveCommitmentKeys( localCommitmentKeys := DeriveCommitmentKeys(
localCommitPoint, true, chanType, ourChanCfg, theirChanCfg, localCommitPoint, true, chanType, ourChanCfg, theirChanCfg,
@@ -1258,7 +1258,8 @@ func CreateCommitmentTxns(localBalance, remoteBalance btcutil.Amount,
ourCommitTx, err := CreateCommitTx( ourCommitTx, err := CreateCommitTx(
chanType, fundingTxIn, localCommitmentKeys, ourChanCfg, chanType, fundingTxIn, localCommitmentKeys, ourChanCfg,
theirChanCfg, localBalance, remoteBalance, 0, theirChanCfg, localBalance, remoteBalance, 0, initiator,
leaseExpiry,
) )
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
@@ -1271,7 +1272,8 @@ func CreateCommitmentTxns(localBalance, remoteBalance btcutil.Amount,
theirCommitTx, err := CreateCommitTx( theirCommitTx, err := CreateCommitTx(
chanType, fundingTxIn, remoteCommitmentKeys, theirChanCfg, chanType, fundingTxIn, remoteCommitmentKeys, theirChanCfg,
ourChanCfg, remoteBalance, localBalance, 0, ourChanCfg, remoteBalance, localBalance, 0, !initiator,
leaseExpiry,
) )
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
@@ -1522,12 +1524,17 @@ func (l *LightningWallet) handleChanPointReady(req *continueContributionMsg) {
// With the funding tx complete, create both commitment transactions. // With the funding tx complete, create both commitment transactions.
localBalance := pendingReservation.partialState.LocalCommitment.LocalBalance.ToSatoshis() localBalance := pendingReservation.partialState.LocalCommitment.LocalBalance.ToSatoshis()
remoteBalance := pendingReservation.partialState.LocalCommitment.RemoteBalance.ToSatoshis() remoteBalance := pendingReservation.partialState.LocalCommitment.RemoteBalance.ToSatoshis()
var leaseExpiry uint32
if pendingReservation.partialState.ChanType.HasLeaseExpiration() {
leaseExpiry = pendingReservation.partialState.ThawHeight
}
ourCommitTx, theirCommitTx, err := CreateCommitmentTxns( ourCommitTx, theirCommitTx, err := CreateCommitmentTxns(
localBalance, remoteBalance, ourContribution.ChannelConfig, localBalance, remoteBalance, ourContribution.ChannelConfig,
theirContribution.ChannelConfig, theirContribution.ChannelConfig,
ourContribution.FirstCommitmentPoint, ourContribution.FirstCommitmentPoint,
theirContribution.FirstCommitmentPoint, fundingTxIn, theirContribution.FirstCommitmentPoint, fundingTxIn,
pendingReservation.partialState.ChanType, pendingReservation.partialState.ChanType,
pendingReservation.partialState.IsInitiator, leaseExpiry,
) )
if err != nil { if err != nil {
req.err <- err req.err <- err
@@ -1894,6 +1901,10 @@ func (l *LightningWallet) handleSingleFunderSigs(req *addSingleFunderSigsMsg) {
// remote node's commitment transactions. // remote node's commitment transactions.
localBalance := pendingReservation.partialState.LocalCommitment.LocalBalance.ToSatoshis() localBalance := pendingReservation.partialState.LocalCommitment.LocalBalance.ToSatoshis()
remoteBalance := pendingReservation.partialState.LocalCommitment.RemoteBalance.ToSatoshis() remoteBalance := pendingReservation.partialState.LocalCommitment.RemoteBalance.ToSatoshis()
var leaseExpiry uint32
if pendingReservation.partialState.ChanType.HasLeaseExpiration() {
leaseExpiry = pendingReservation.partialState.ThawHeight
}
ourCommitTx, theirCommitTx, err := CreateCommitmentTxns( ourCommitTx, theirCommitTx, err := CreateCommitmentTxns(
localBalance, remoteBalance, localBalance, remoteBalance,
pendingReservation.ourContribution.ChannelConfig, pendingReservation.ourContribution.ChannelConfig,
@@ -1901,6 +1912,7 @@ func (l *LightningWallet) handleSingleFunderSigs(req *addSingleFunderSigsMsg) {
pendingReservation.ourContribution.FirstCommitmentPoint, pendingReservation.ourContribution.FirstCommitmentPoint,
pendingReservation.theirContribution.FirstCommitmentPoint, pendingReservation.theirContribution.FirstCommitmentPoint,
*fundingTxIn, pendingReservation.partialState.ChanType, *fundingTxIn, pendingReservation.partialState.ChanType,
pendingReservation.partialState.IsInitiator, leaseExpiry,
) )
if err != nil { if err != nil {
req.err <- err req.err <- err

View File

@@ -79,6 +79,7 @@ func createTestPeer(notifier chainntnfs.ChainNotifier,
bobDustLimit := btcutil.Amount(1300) bobDustLimit := btcutil.Amount(1300)
csvTimeoutAlice := uint32(5) csvTimeoutAlice := uint32(5)
csvTimeoutBob := uint32(4) csvTimeoutBob := uint32(4)
isAliceInitiator := true
prevOut := &wire.OutPoint{ prevOut := &wire.OutPoint{
Hash: channels.TestHdSeed, Hash: channels.TestHdSeed,
@@ -162,6 +163,7 @@ func createTestPeer(notifier chainntnfs.ChainNotifier,
aliceCommitTx, bobCommitTx, err := lnwallet.CreateCommitmentTxns( aliceCommitTx, bobCommitTx, err := lnwallet.CreateCommitmentTxns(
channelBal, channelBal, &aliceCfg, &bobCfg, aliceCommitPoint, channelBal, channelBal, &aliceCfg, &bobCfg, aliceCommitPoint,
bobCommitPoint, *fundingTxIn, channeldb.SingleFunderTweaklessBit, bobCommitPoint, *fundingTxIn, channeldb.SingleFunderTweaklessBit,
isAliceInitiator, 0,
) )
if err != nil { if err != nil {
return nil, nil, nil, err return nil, nil, nil, err
@@ -229,7 +231,7 @@ func createTestPeer(notifier chainntnfs.ChainNotifier,
FundingOutpoint: *prevOut, FundingOutpoint: *prevOut,
ShortChannelID: shortChanID, ShortChannelID: shortChanID,
ChanType: channeldb.SingleFunderTweaklessBit, ChanType: channeldb.SingleFunderTweaklessBit,
IsInitiator: true, IsInitiator: isAliceInitiator,
Capacity: channelCapacity, Capacity: channelCapacity,
RemoteCurrentRevocation: bobCommitPoint, RemoteCurrentRevocation: bobCommitPoint,
RevocationProducer: alicePreimageProducer, RevocationProducer: alicePreimageProducer,
@@ -246,7 +248,7 @@ func createTestPeer(notifier chainntnfs.ChainNotifier,
IdentityPub: bobKeyPub, IdentityPub: bobKeyPub,
FundingOutpoint: *prevOut, FundingOutpoint: *prevOut,
ChanType: channeldb.SingleFunderTweaklessBit, ChanType: channeldb.SingleFunderTweaklessBit,
IsInitiator: false, IsInitiator: !isAliceInitiator,
Capacity: channelCapacity, Capacity: channelCapacity,
RemoteCurrentRevocation: aliceCommitPoint, RemoteCurrentRevocation: aliceCommitPoint,
RevocationProducer: bobPreimageProducer, RevocationProducer: bobPreimageProducer,