mirror of
https://github.com/aljazceru/breez-lnd.git
synced 2025-12-17 06:04:20 +01:00
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:
committed by
Olaoluwa Osuntokun
parent
01e9bb2bff
commit
8cfb53f64a
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 (
|
||||||
|
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,
|
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
|
||||||
}
|
|
||||||
|
|
||||||
|
default:
|
||||||
// Otherwise the to_remote will be a simple p2wkh.
|
// Otherwise the to_remote will be a simple p2wkh.
|
||||||
p2wkh, err := input.CommitScriptUnencumbered(key)
|
p2wkh, err := input.CommitScriptUnencumbered(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
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 (
|
||||||
|
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,
|
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
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user