diff --git a/breacharbiter_test.go b/breacharbiter_test.go index 9d95ea4f0..b4f1c5683 100644 --- a/breacharbiter_test.go +++ b/breacharbiter_test.go @@ -90,6 +90,11 @@ var ( 0x2e, 0x9c, 0x51, 0x0f, 0x8e, 0xf5, 0x2b, 0xd0, 0x21, 0xa9, 0xa1, 0xf4, 0x80, 0x9d, 0x3b, 0x4d, }, + {0x02, 0xce, 0x0b, 0x14, 0xfb, 0x84, 0x2b, 0x1b, + 0x2e, 0x9c, 0x51, 0x0f, 0x8e, 0xf5, 0x2b, 0xd0, 0x21, + 0xa5, 0x49, 0xfd, 0xd6, 0x75, 0xc9, 0x80, 0x75, 0xf1, + 0xa3, 0xa1, 0xf4, 0x80, 0x9d, 0x3b, 0x4d, + }, } breachedOutputs = []breachedOutput{ @@ -1754,9 +1759,10 @@ func createInitChannels(revocationWindow int) (*lnwallet.LightningChannel, *lnwa } aliceCommitPoint := input.ComputeCommitmentPoint(aliceFirstRevoke[:]) - aliceCommitTx, bobCommitTx, err := lnwallet.CreateCommitmentTxns(channelBal, - channelBal, &aliceCfg, &bobCfg, aliceCommitPoint, bobCommitPoint, - *fundingTxIn) + aliceCommitTx, bobCommitTx, err := lnwallet.CreateCommitmentTxns( + channelBal, channelBal, &aliceCfg, &bobCfg, aliceCommitPoint, + bobCommitPoint, *fundingTxIn, true, + ) if err != nil { return nil, nil, nil, err } @@ -1822,7 +1828,7 @@ func createInitChannels(revocationWindow int) (*lnwallet.LightningChannel, *lnwa IdentityPub: aliceKeyPub, FundingOutpoint: *prevOut, ShortChannelID: shortChanID, - ChanType: channeldb.SingleFunder, + ChanType: channeldb.SingleFunderTweakless, IsInitiator: true, Capacity: channelCapacity, RemoteCurrentRevocation: bobCommitPoint, @@ -1840,7 +1846,7 @@ func createInitChannels(revocationWindow int) (*lnwallet.LightningChannel, *lnwa IdentityPub: bobKeyPub, FundingOutpoint: *prevOut, ShortChannelID: shortChanID, - ChanType: channeldb.SingleFunder, + ChanType: channeldb.SingleFunderTweakless, IsInitiator: false, Capacity: channelCapacity, RemoteCurrentRevocation: aliceCommitPoint, diff --git a/contractcourt/chain_arbitrator_test.go b/contractcourt/chain_arbitrator_test.go index 4ff3d0644..38ea2a35b 100644 --- a/contractcourt/chain_arbitrator_test.go +++ b/contractcourt/chain_arbitrator_test.go @@ -34,7 +34,7 @@ func TestChainArbitratorRepublishCommitment(t *testing.T) { const numChans = 10 var channels []*channeldb.OpenChannel for i := 0; i < numChans; i++ { - lChannel, _, cleanup, err := lnwallet.CreateTestChannels() + lChannel, _, cleanup, err := lnwallet.CreateTestChannels(true) if err != nil { t.Fatal(err) } diff --git a/contractcourt/chain_watcher_test.go b/contractcourt/chain_watcher_test.go index 2a511b653..f0e07628b 100644 --- a/contractcourt/chain_watcher_test.go +++ b/contractcourt/chain_watcher_test.go @@ -62,7 +62,7 @@ func TestChainWatcherRemoteUnilateralClose(t *testing.T) { // First, we'll create two channels which already have established a // commitment contract between themselves. - aliceChannel, bobChannel, cleanUp, err := lnwallet.CreateTestChannels() + aliceChannel, bobChannel, cleanUp, err := lnwallet.CreateTestChannels(true) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -149,7 +149,7 @@ func TestChainWatcherRemoteUnilateralClosePendingCommit(t *testing.T) { // First, we'll create two channels which already have established a // commitment contract between themselves. - aliceChannel, bobChannel, cleanUp, err := lnwallet.CreateTestChannels() + aliceChannel, bobChannel, cleanUp, err := lnwallet.CreateTestChannels(true) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -272,7 +272,9 @@ func TestChainWatcherDataLossProtect(t *testing.T) { dlpScenario := func(t *testing.T, testCase dlpTestCase) bool { // First, we'll create two channels which already have // established a commitment contract between themselves. - aliceChannel, bobChannel, cleanUp, err := lnwallet.CreateTestChannels() + aliceChannel, bobChannel, cleanUp, err := lnwallet.CreateTestChannels( + false, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -430,7 +432,7 @@ func TestChainWatcherDataLossProtect(t *testing.T) { func TestChainWatcherLocalForceCloseDetect(t *testing.T) { t.Parallel() - // localForceCloseScenario is the primary test we'll use to execut eout + // localForceCloseScenario is the primary test we'll use to execute our // table driven tests. We'll assert that for any number of state // updates, and if the commitment transaction has our output or not, // we're able to properly detect a local force close. @@ -439,7 +441,9 @@ func TestChainWatcherLocalForceCloseDetect(t *testing.T) { // First, we'll create two channels which already have // established a commitment contract between themselves. - aliceChannel, bobChannel, cleanUp, err := lnwallet.CreateTestChannels() + aliceChannel, bobChannel, cleanUp, err := lnwallet.CreateTestChannels( + false, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } diff --git a/htlcswitch/test_utils.go b/htlcswitch/test_utils.go index 4f48c4f62..f2f86b752 100644 --- a/htlcswitch/test_utils.go +++ b/htlcswitch/test_utils.go @@ -327,7 +327,7 @@ func createTestChannel(alicePrivKey, bobPrivKey []byte, RemoteChanCfg: bobCfg, IdentityPub: aliceKeyPub, FundingOutpoint: *prevOut, - ChanType: channeldb.SingleFunder, + ChanType: channeldb.SingleFunderTweakless, IsInitiator: true, Capacity: channelCapacity, RemoteCurrentRevocation: bobCommitPoint, @@ -346,7 +346,7 @@ func createTestChannel(alicePrivKey, bobPrivKey []byte, RemoteChanCfg: aliceCfg, IdentityPub: bobKeyPub, FundingOutpoint: *prevOut, - ChanType: channeldb.SingleFunder, + ChanType: channeldb.SingleFunderTweakless, IsInitiator: false, Capacity: channelCapacity, RemoteCurrentRevocation: aliceCommitPoint, diff --git a/lnwallet/interface_test.go b/lnwallet/interface_test.go index deda71e71..16bb88e00 100644 --- a/lnwallet/interface_test.go +++ b/lnwallet/interface_test.go @@ -698,7 +698,7 @@ func testCancelNonExistentReservation(miner *rpctest.Harness, // Create our own reservation, give it some ID. res, err := lnwallet.NewChannelReservation( 10000, 10000, feePerKw, alice, 22, 10, &testHdSeed, - lnwire.FFAnnounceChannel, + lnwire.FFAnnounceChannel, true, ) if err != nil { t.Fatalf("unable to create res: %v", err) @@ -736,6 +736,7 @@ func testReservationInitiatorBalanceBelowDustCancel(miner *rpctest.Harness, FundingFeePerKw: 1000, PushMSat: 0, Flags: lnwire.FFAnnounceChannel, + Tweakless: true, } _, err = alice.InitChannelReservation(req) switch { @@ -790,7 +791,7 @@ func assertContributionInitPopulated(t *testing.T, c *lnwallet.ChannelContributi } func testSingleFunderReservationWorkflow(miner *rpctest.Harness, - alice, bob *lnwallet.LightningWallet, t *testing.T) { + alice, bob *lnwallet.LightningWallet, t *testing.T, tweakless bool) { // For this scenario, Alice will be the channel initiator while bob // will act as the responder to the workflow. @@ -817,6 +818,7 @@ func testSingleFunderReservationWorkflow(miner *rpctest.Harness, FundingFeePerKw: feePerKw, PushMSat: pushAmt, Flags: lnwire.FFAnnounceChannel, + Tweakless: tweakless, } aliceChanReservation, err := alice.InitChannelReservation(aliceReq) if err != nil { @@ -860,6 +862,7 @@ func testSingleFunderReservationWorkflow(miner *rpctest.Harness, FundingFeePerKw: feePerKw, PushMSat: pushAmt, Flags: lnwire.FFAnnounceChannel, + Tweakless: tweakless, } bobChanReservation, err := bob.InitChannelReservation(bobReq) if err != nil { @@ -966,7 +969,7 @@ func testSingleFunderReservationWorkflow(miner *rpctest.Harness, if !aliceChannels[0].IsInitiator { t.Fatalf("alice not detected as channel initiator") } - if aliceChannels[0].ChanType != channeldb.SingleFunder { + if !aliceChannels[0].ChanType.IsSingleFunder() { t.Fatalf("channel type is incorrect, expected %v instead got %v", channeldb.SingleFunder, aliceChannels[0].ChanType) } @@ -986,7 +989,7 @@ func testSingleFunderReservationWorkflow(miner *rpctest.Harness, if bobChannels[0].IsInitiator { t.Fatalf("bob not detected as channel responder") } - if bobChannels[0].ChanType != channeldb.SingleFunder { + if !bobChannels[0].ChanType.IsSingleFunder() { t.Fatalf("channel type is incorrect, expected %v instead got %v", channeldb.SingleFunder, bobChannels[0].ChanType) } @@ -2515,7 +2518,23 @@ var walletTests = []walletTestCase{ }, { name: "single funding workflow", - test: testSingleFunderReservationWorkflow, + test: func(miner *rpctest.Harness, alice, + bob *lnwallet.LightningWallet, t *testing.T) { + + testSingleFunderReservationWorkflow( + miner, alice, bob, t, false, + ) + }, + }, + { + name: "single funding workflow tweakless", + test: func(miner *rpctest.Harness, alice, + bob *lnwallet.LightningWallet, t *testing.T) { + + testSingleFunderReservationWorkflow( + miner, alice, bob, t, true, + ) + }, }, { name: "dual funder workflow", diff --git a/lnwallet/reservation.go b/lnwallet/reservation.go index 98c88d724..6ac592b9f 100644 --- a/lnwallet/reservation.go +++ b/lnwallet/reservation.go @@ -130,7 +130,8 @@ type ChannelReservation struct { func NewChannelReservation(capacity, localFundingAmt btcutil.Amount, commitFeePerKw SatPerKWeight, wallet *LightningWallet, id uint64, pushMSat lnwire.MilliSatoshi, chainHash *chainhash.Hash, - flags lnwire.FundingFlag) (*ChannelReservation, error) { + flags lnwire.FundingFlag, + tweaklessCommit bool) (*ChannelReservation, error) { var ( ourBalance lnwire.MilliSatoshi @@ -140,7 +141,7 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount, commitFee := commitFeePerKw.FeeForWeight(input.CommitWeight) localFundingMSat := lnwire.NewMSatFromSatoshis(localFundingAmt) - // TODO(halseth): make method take remote funding amount direcly + // TODO(halseth): make method take remote funding amount directly // instead of inferring it from capacity and local amt. capacityMSat := lnwire.NewMSatFromSatoshis(capacity) feeMSat := lnwire.NewMSatFromSatoshis(commitFee) @@ -213,7 +214,11 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount, // non-zero push amt (there's no pushing for dual funder), then this is // a single-funder channel. if ourBalance == 0 || theirBalance == 0 || pushMSat != 0 { - chanType = channeldb.SingleFunder + if tweaklessCommit { + chanType = channeldb.SingleFunderTweakless + } else { + chanType = channeldb.SingleFunder + } } else { // Otherwise, this is a dual funder channel, and no side is // technically the "initiator" diff --git a/lnwallet/test_utils.go b/lnwallet/test_utils.go index 579622fa4..efb30ac1d 100644 --- a/lnwallet/test_utils.go +++ b/lnwallet/test_utils.go @@ -88,8 +88,11 @@ var ( // allocated to each side. Within the channel, Alice is the initiator. The // function also returns a "cleanup" function that is meant to be called once // the test has been finalized. The clean up function will remote all temporary -// files created -func CreateTestChannels(tweaklessCommits bool) (*LightningChannel, *LightningChannel, func(), error) { +// files created. If tweaklessCommits is true, then the commits within the +// channels will use the new format, otherwise the legacy format. +func CreateTestChannels(tweaklessCommits bool) ( + *LightningChannel, *LightningChannel, func(), error) { + channelCapacity, err := btcutil.NewAmount(10) if err != nil { return nil, nil, nil, err @@ -271,7 +274,7 @@ func CreateTestChannels(tweaklessCommits bool) (*LightningChannel, *LightningCha IdentityPub: aliceKeys[0].PubKey(), FundingOutpoint: *prevOut, ShortChannelID: shortChanID, - ChanType: channeldb.SingleFunder, + ChanType: channeldb.SingleFunderTweakless, IsInitiator: true, Capacity: channelCapacity, RemoteCurrentRevocation: bobCommitPoint, @@ -289,7 +292,7 @@ func CreateTestChannels(tweaklessCommits bool) (*LightningChannel, *LightningCha IdentityPub: bobKeys[0].PubKey(), FundingOutpoint: *prevOut, ShortChannelID: shortChanID, - ChanType: channeldb.SingleFunder, + ChanType: channeldb.SingleFunderTweakless, IsInitiator: false, Capacity: channelCapacity, RemoteCurrentRevocation: aliceCommitPoint, @@ -301,6 +304,11 @@ func CreateTestChannels(tweaklessCommits bool) (*LightningChannel, *LightningCha Packager: channeldb.NewChannelPackager(shortChanID), } + if !tweaklessCommits { + aliceChannelState.ChanType = channeldb.SingleFunder + bobChannelState.ChanType = channeldb.SingleFunder + } + aliceSigner := &input.MockSigner{Privkeys: aliceKeys} bobSigner := &input.MockSigner{Privkeys: bobKeys} diff --git a/lnwallet/wallet.go b/lnwallet/wallet.go index f86afb615..0e75e585e 100644 --- a/lnwallet/wallet.go +++ b/lnwallet/wallet.go @@ -106,6 +106,10 @@ type InitFundingReserveMsg struct { // output selected to fund the channel should satisfy. MinConfs int32 + // Tweakless indicates if the channel should use the new tweakless + // commitment format or not. + Tweakless bool + // err is a channel in which all errors will be sent across. Will be // nil if this initial set is successful. // @@ -489,6 +493,7 @@ func (l *LightningWallet) handleFundingReserveRequest(req *InitFundingReserveMsg reservation, err := NewChannelReservation( capacity, localFundingAmt, req.CommitFeePerKw, l, id, req.PushMSat, l.Cfg.NetParams.GenesisHash, req.Flags, + req.Tweakless, ) if err != nil { selected.unlockCoins() @@ -849,7 +854,7 @@ func (l *LightningWallet) handleContributionMsg(req *addContributionMsg) { // obfuscator then use it to encode the current state number within // both commitment transactions. var stateObfuscator [StateHintSize]byte - if chanState.ChanType == channeldb.SingleFunder { + if chanState.ChanType.IsSingleFunder() { stateObfuscator = DeriveStateHintObfuscator( ourContribution.PaymentBasePoint.PubKey, theirContribution.PaymentBasePoint.PubKey, diff --git a/test_utils.go b/test_utils.go index cce87d542..671bc0f46 100644 --- a/test_utils.go +++ b/test_utils.go @@ -255,7 +255,7 @@ func createTestPeer(notifier chainntnfs.ChainNotifier, IdentityPub: aliceKeyPub, FundingOutpoint: *prevOut, ShortChannelID: shortChanID, - ChanType: channeldb.SingleFunder, + ChanType: channeldb.SingleFunderTweakless, IsInitiator: true, Capacity: channelCapacity, RemoteCurrentRevocation: bobCommitPoint, @@ -272,7 +272,7 @@ func createTestPeer(notifier chainntnfs.ChainNotifier, RemoteChanCfg: aliceCfg, IdentityPub: bobKeyPub, FundingOutpoint: *prevOut, - ChanType: channeldb.SingleFunder, + ChanType: channeldb.SingleFunderTweakless, IsInitiator: false, Capacity: channelCapacity, RemoteCurrentRevocation: aliceCommitPoint,