lnd_zero_conf_test.go 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002
  1. package itest
  2. import (
  3. "fmt"
  4. "testing"
  5. "time"
  6. "github.com/btcsuite/btcd/btcutil"
  7. "github.com/go-errors/errors"
  8. "github.com/lightningnetwork/lnd/aliasmgr"
  9. "github.com/lightningnetwork/lnd/chainreg"
  10. "github.com/lightningnetwork/lnd/lnrpc"
  11. "github.com/lightningnetwork/lnd/lnrpc/routerrpc"
  12. "github.com/lightningnetwork/lnd/lntest"
  13. "github.com/lightningnetwork/lnd/lntest/node"
  14. "github.com/lightningnetwork/lnd/lntest/rpc"
  15. "github.com/lightningnetwork/lnd/lntest/wait"
  16. "github.com/lightningnetwork/lnd/lnwire"
  17. "github.com/stretchr/testify/require"
  18. )
  19. // testZeroConfChannelOpen tests that opening a zero-conf channel works and
  20. // sending payments also works.
  21. func testZeroConfChannelOpen(ht *lntest.HarnessTest) {
  22. // Since option-scid-alias is opt-in, the provided harness nodes will
  23. // not have the feature bit set. Also need to set anchors as those are
  24. // default-off in itests.
  25. scidAliasArgs := []string{
  26. "--protocol.option-scid-alias",
  27. "--protocol.zero-conf",
  28. "--protocol.anchors",
  29. }
  30. bob := ht.Bob
  31. carol := ht.NewNode("Carol", scidAliasArgs)
  32. ht.EnsureConnected(bob, carol)
  33. // We'll open a regular public channel between Bob and Carol here.
  34. chanAmt := btcutil.Amount(1_000_000)
  35. p := lntest.OpenChannelParams{
  36. Amt: chanAmt,
  37. }
  38. chanPoint := ht.OpenChannel(bob, carol, p)
  39. // Spin-up Dave so Carol can open a zero-conf channel to him.
  40. dave := ht.NewNode("Dave", scidAliasArgs)
  41. // We'll give Carol some coins in order to fund the channel.
  42. ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
  43. // Ensure that both Carol and Dave are connected.
  44. ht.EnsureConnected(carol, dave)
  45. // Setup a ChannelAcceptor for Dave.
  46. acceptStream, cancel := dave.RPC.ChannelAcceptor()
  47. go acceptChannel(ht.T, true, acceptStream)
  48. // Open a private zero-conf anchors channel of 1M satoshis.
  49. params := lntest.OpenChannelParams{
  50. Amt: chanAmt,
  51. Private: true,
  52. CommitmentType: lnrpc.CommitmentType_ANCHORS,
  53. ZeroConf: true,
  54. }
  55. stream := ht.OpenChannelAssertStream(carol, dave, params)
  56. // Remove the ChannelAcceptor.
  57. cancel()
  58. // We should receive the OpenStatusUpdate_ChanOpen update without
  59. // having to mine any blocks.
  60. fundingPoint2 := ht.WaitForChannelOpenEvent(stream)
  61. ht.AssertTopologyChannelOpen(carol, fundingPoint2)
  62. ht.AssertTopologyChannelOpen(dave, fundingPoint2)
  63. // Attempt to send a 10K satoshi payment from Carol to Dave.
  64. daveInvoiceParams := &lnrpc.Invoice{
  65. Value: int64(10_000),
  66. Private: true,
  67. }
  68. daveInvoiceResp := dave.RPC.AddInvoice(daveInvoiceParams)
  69. ht.CompletePaymentRequests(
  70. carol, []string{daveInvoiceResp.PaymentRequest},
  71. )
  72. // Now attempt to send a multi-hop payment from Bob to Dave. This tests
  73. // that Dave issues an invoice with an alias SCID that Carol knows and
  74. // uses to forward to Dave.
  75. daveInvoiceResp2 := dave.RPC.AddInvoice(daveInvoiceParams)
  76. ht.CompletePaymentRequests(
  77. bob, []string{daveInvoiceResp2.PaymentRequest},
  78. )
  79. // Check that Dave has a zero-conf alias SCID in the graph.
  80. descReq := &lnrpc.ChannelGraphRequest{
  81. IncludeUnannounced: true,
  82. }
  83. err := waitForZeroConfGraphChange(dave, descReq, true)
  84. require.NoError(ht, err)
  85. // We'll now confirm the zero-conf channel between Carol and Dave and
  86. // assert that sending is still possible.
  87. block := ht.MineBlocksAndAssertNumTxes(6, 1)[0]
  88. // Dave should still have the alias edge in his db.
  89. err = waitForZeroConfGraphChange(dave, descReq, true)
  90. require.NoError(ht, err)
  91. fundingTxID := ht.GetChanPointFundingTxid(fundingPoint2)
  92. ht.Miner.AssertTxInBlock(block, fundingTxID)
  93. daveInvoiceResp3 := dave.RPC.AddInvoice(daveInvoiceParams)
  94. ht.CompletePaymentRequests(
  95. bob, []string{daveInvoiceResp3.PaymentRequest},
  96. )
  97. // Eve will now initiate a zero-conf channel with Carol. This tests
  98. // that the ChannelUpdates sent are correct since they will be
  99. // referring to different alias SCIDs.
  100. eve := ht.NewNode("Eve", scidAliasArgs)
  101. ht.EnsureConnected(eve, carol)
  102. // Give Eve some coins to fund the channel.
  103. ht.FundCoins(btcutil.SatoshiPerBitcoin, eve)
  104. // Setup a ChannelAcceptor.
  105. acceptStream, cancel = carol.RPC.ChannelAcceptor()
  106. go acceptChannel(ht.T, true, acceptStream)
  107. // We'll open a public zero-conf anchors channel of 1M satoshis.
  108. params.Private = false
  109. stream = ht.OpenChannelAssertStream(eve, carol, params)
  110. // Remove the ChannelAcceptor.
  111. cancel()
  112. // Wait to receive the OpenStatusUpdate_ChanOpen update.
  113. fundingPoint3 := ht.WaitForChannelOpenEvent(stream)
  114. ht.AssertTopologyChannelOpen(eve, fundingPoint3)
  115. ht.AssertTopologyChannelOpen(carol, fundingPoint3)
  116. // Attempt to send a 20K satoshi payment from Eve to Dave.
  117. daveInvoiceParams.Value = int64(20_000)
  118. daveInvoiceResp4 := dave.RPC.AddInvoice(daveInvoiceParams)
  119. ht.CompletePaymentRequests(
  120. eve, []string{daveInvoiceResp4.PaymentRequest},
  121. )
  122. // Assert that Eve has stored the zero-conf alias in her graph.
  123. err = waitForZeroConfGraphChange(eve, descReq, true)
  124. require.NoError(ht, err, "expected to not receive error")
  125. // We'll confirm the zero-conf channel between Eve and Carol and assert
  126. // that sending is still possible.
  127. block = ht.MineBlocksAndAssertNumTxes(6, 1)[0]
  128. fundingTxID = ht.GetChanPointFundingTxid(fundingPoint3)
  129. ht.Miner.AssertTxInBlock(block, fundingTxID)
  130. // Wait until Eve's ZeroConf channel is replaced by the confirmed SCID
  131. // in her graph.
  132. err = waitForZeroConfGraphChange(eve, descReq, false)
  133. require.NoError(ht, err, "expected to not receive error")
  134. // Attempt to send a 6K satoshi payment from Dave to Eve.
  135. eveInvoiceParams := &lnrpc.Invoice{
  136. Value: int64(6_000),
  137. Private: true,
  138. }
  139. eveInvoiceResp := eve.RPC.AddInvoice(eveInvoiceParams)
  140. // Assert that route hints is empty since the channel is public.
  141. payReq := eve.RPC.DecodePayReq(eveInvoiceResp.PaymentRequest)
  142. require.Len(ht, payReq.RouteHints, 0)
  143. // Make sure Dave is aware of this channel and send the payment.
  144. ht.AssertTopologyChannelOpen(dave, fundingPoint3)
  145. ht.CompletePaymentRequests(
  146. dave, []string{eveInvoiceResp.PaymentRequest},
  147. )
  148. // Close standby node's channels.
  149. ht.CloseChannel(bob, chanPoint)
  150. }
  151. // testOptionScidAlias checks that opening an option_scid_alias channel-type
  152. // channel or w/o the channel-type works properly.
  153. func testOptionScidAlias(ht *lntest.HarnessTest) {
  154. type scidTestCase struct {
  155. name string
  156. // If this is false, then the channel will be a regular non
  157. // channel-type option-scid-alias-feature-bit channel.
  158. chantype bool
  159. private bool
  160. }
  161. var testCases = []scidTestCase{
  162. {
  163. name: "private chan-type",
  164. chantype: true,
  165. private: true,
  166. },
  167. {
  168. name: "public no chan-type",
  169. chantype: false,
  170. private: false,
  171. },
  172. {
  173. name: "private no chan-type",
  174. chantype: false,
  175. private: true,
  176. },
  177. }
  178. for _, testCase := range testCases {
  179. testCase := testCase
  180. success := ht.Run(testCase.name, func(t *testing.T) {
  181. st := ht.Subtest(t)
  182. optionScidAliasScenario(
  183. st, testCase.chantype, testCase.private,
  184. )
  185. })
  186. if !success {
  187. break
  188. }
  189. }
  190. }
  191. func optionScidAliasScenario(ht *lntest.HarnessTest, chantype, private bool) {
  192. // Option-scid-alias is opt-in, as is anchors.
  193. scidAliasArgs := []string{
  194. "--protocol.option-scid-alias",
  195. "--protocol.anchors",
  196. }
  197. bob := ht.Bob
  198. carol := ht.NewNode("Carol", scidAliasArgs)
  199. dave := ht.NewNode("Dave", scidAliasArgs)
  200. // Ensure Bob, Carol are connected.
  201. ht.EnsureConnected(bob, carol)
  202. // Ensure Carol, Dave are connected.
  203. ht.EnsureConnected(carol, dave)
  204. // Give Carol some coins so she can open the channel.
  205. ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
  206. chanAmt := btcutil.Amount(1_000_000)
  207. params := lntest.OpenChannelParams{
  208. Amt: chanAmt,
  209. Private: private,
  210. CommitmentType: lnrpc.CommitmentType_ANCHORS,
  211. ScidAlias: chantype,
  212. }
  213. fundingPoint := ht.OpenChannel(carol, dave, params)
  214. // Make sure Bob knows this channel if it's public.
  215. if !private {
  216. ht.AssertTopologyChannelOpen(bob, fundingPoint)
  217. }
  218. // Assert that a payment from Carol to Dave works as expected.
  219. daveInvoiceParams := &lnrpc.Invoice{
  220. Value: int64(10_000),
  221. Private: true,
  222. }
  223. daveInvoiceResp := dave.RPC.AddInvoice(daveInvoiceParams)
  224. ht.CompletePaymentRequests(
  225. carol, []string{daveInvoiceResp.PaymentRequest},
  226. )
  227. // We'll now open a regular public channel between Bob and Carol and
  228. // assert that Bob can pay Dave. We'll also assert that the invoice
  229. // Dave issues has the startingAlias as a hop hint.
  230. p := lntest.OpenChannelParams{
  231. Amt: chanAmt,
  232. }
  233. fundingPoint2 := ht.OpenChannel(bob, carol, p)
  234. defer func() {
  235. // TODO(yy): remove the sleep once the following bug is fixed.
  236. // When the payment is reported as settled by Bob, it's
  237. // expected the commitment dance is finished and all subsequent
  238. // states have been updated. Yet we'd receive the error `cannot
  239. // co-op close channel with active htlcs` or `link failed to
  240. // shutdown` if we close the channel. We need to investigate
  241. // the order of settling the payments and updating commitments
  242. // to understand and fix.
  243. time.Sleep(2 * time.Second)
  244. // Close standby node's channels.
  245. ht.CloseChannel(bob, fundingPoint2)
  246. }()
  247. // Wait until Dave receives the Bob<->Carol channel.
  248. ht.AssertTopologyChannelOpen(dave, fundingPoint2)
  249. daveInvoiceResp2 := dave.RPC.AddInvoice(daveInvoiceParams)
  250. decodedReq := dave.RPC.DecodePayReq(daveInvoiceResp2.PaymentRequest)
  251. if !private {
  252. require.Len(ht, decodedReq.RouteHints, 0)
  253. payReq := daveInvoiceResp2.PaymentRequest
  254. ht.CompletePaymentRequests(bob, []string{payReq})
  255. return
  256. }
  257. require.Len(ht, decodedReq.RouteHints, 1)
  258. require.Len(ht, decodedReq.RouteHints[0].HopHints, 1)
  259. startingAlias := lnwire.ShortChannelID{
  260. BlockHeight: 16_000_000,
  261. TxIndex: 0,
  262. TxPosition: 0,
  263. }
  264. daveHopHint := decodedReq.RouteHints[0].HopHints[0].ChanId
  265. require.Equal(ht, startingAlias.ToUint64(), daveHopHint)
  266. ht.CompletePaymentRequests(
  267. bob, []string{daveInvoiceResp2.PaymentRequest},
  268. )
  269. }
  270. // waitForZeroConfGraphChange waits for the zero-conf channel to be visible in
  271. // the graph after confirmation or not. The expect argument denotes whether the
  272. // zero-conf is expected in the graph or not. There should always be at least
  273. // one channel of the passed HarnessNode, zero-conf or not.
  274. func waitForZeroConfGraphChange(hn *node.HarnessNode,
  275. req *lnrpc.ChannelGraphRequest, expect bool) error {
  276. return wait.NoError(func() error {
  277. graph := hn.RPC.DescribeGraph(req)
  278. if expect {
  279. // If we expect a zero-conf channel, we'll assert that
  280. // one exists, both policies exist, and we are party to
  281. // the channel.
  282. for _, e := range graph.Edges {
  283. // The BlockHeight will be less than 16_000_000
  284. // if this is not a zero-conf channel.
  285. scid := lnwire.NewShortChanIDFromInt(
  286. e.ChannelId,
  287. )
  288. if scid.BlockHeight < 16_000_000 {
  289. continue
  290. }
  291. // Both edge policies must exist in the zero
  292. // conf case.
  293. if e.Node1Policy == nil ||
  294. e.Node2Policy == nil {
  295. continue
  296. }
  297. // Check if we are party to the zero-conf
  298. // channel.
  299. if e.Node1Pub == hn.PubKeyStr ||
  300. e.Node2Pub == hn.PubKeyStr {
  301. return nil
  302. }
  303. }
  304. return errors.New("failed to find zero-conf channel " +
  305. "in graph")
  306. }
  307. // If we don't expect a zero-conf channel, we'll assert that
  308. // none exist, that we have a non-zero-conf channel with at
  309. // both policies, and one of the policies in the database is
  310. // ours.
  311. for _, e := range graph.Edges {
  312. scid := lnwire.NewShortChanIDFromInt(e.ChannelId)
  313. if scid.BlockHeight == 16_000_000 {
  314. return errors.New("found zero-conf channel")
  315. }
  316. // One of the edge policies must exist.
  317. if e.Node1Policy == nil || e.Node2Policy == nil {
  318. continue
  319. }
  320. // If we are part of this channel, exit gracefully.
  321. if e.Node1Pub == hn.PubKeyStr ||
  322. e.Node2Pub == hn.PubKeyStr {
  323. return nil
  324. }
  325. }
  326. return errors.New(
  327. "failed to find non-zero-conf channel in graph",
  328. )
  329. }, defaultTimeout)
  330. }
  331. // testUpdateChannelPolicyScidAlias checks that option-scid-alias, zero-conf
  332. // channel-types, and option-scid-alias feature-bit-only channels have the
  333. // expected graph and that payments work when updating the channel policy.
  334. func testUpdateChannelPolicyScidAlias(ht *lntest.HarnessTest) {
  335. tests := []struct {
  336. name string
  337. // The option-scid-alias channel type.
  338. scidAliasType bool
  339. // The zero-conf channel type.
  340. zeroConf bool
  341. private bool
  342. }{
  343. {
  344. name: "private scid-alias chantype update",
  345. scidAliasType: true,
  346. private: true,
  347. },
  348. {
  349. name: "private zero-conf update",
  350. zeroConf: true,
  351. private: true,
  352. },
  353. {
  354. name: "public zero-conf update",
  355. zeroConf: true,
  356. },
  357. {
  358. name: "public no-chan-type update",
  359. },
  360. {
  361. name: "private no-chan-type update",
  362. private: true,
  363. },
  364. }
  365. for _, test := range tests {
  366. test := test
  367. success := ht.Run(test.name, func(t *testing.T) {
  368. st := ht.Subtest(t)
  369. testPrivateUpdateAlias(
  370. st, test.zeroConf, test.scidAliasType,
  371. test.private,
  372. )
  373. })
  374. if !success {
  375. return
  376. }
  377. }
  378. }
  379. func testPrivateUpdateAlias(ht *lntest.HarnessTest,
  380. zeroConf, scidAliasType, private bool) {
  381. // We'll create a new node Eve that will not have option-scid-alias
  382. // channels.
  383. eve := ht.NewNode("Eve", nil)
  384. ht.FundCoins(btcutil.SatoshiPerBitcoin, eve)
  385. // Since option-scid-alias is opt-in we'll need to specify the protocol
  386. // arguments when creating a new node.
  387. scidAliasArgs := []string{
  388. "--protocol.option-scid-alias",
  389. "--protocol.zero-conf",
  390. "--protocol.anchors",
  391. }
  392. carol := ht.NewNode("Carol", scidAliasArgs)
  393. // Spin-up Dave who will have an option-scid-alias feature-bit-only or
  394. // channel-type channel with Carol.
  395. dave := ht.NewNode("Dave", scidAliasArgs)
  396. // We'll give Carol some coins in order to fund the channel.
  397. ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
  398. // Ensure that Carol and Dave are connected.
  399. ht.EnsureConnected(carol, dave)
  400. // We'll open a regular public channel between Eve and Carol here. Eve
  401. // will be the one receiving the onion-encrypted ChannelUpdate.
  402. ht.EnsureConnected(eve, carol)
  403. chanAmt := btcutil.Amount(1_000_000)
  404. p := lntest.OpenChannelParams{
  405. Amt: chanAmt,
  406. PushAmt: chanAmt / 2,
  407. }
  408. fundingPoint := ht.OpenChannel(eve, carol, p)
  409. // Make sure Dave has seen this public channel.
  410. ht.AssertTopologyChannelOpen(dave, fundingPoint)
  411. // Setup a ChannelAcceptor for Dave.
  412. acceptStream, cancel := dave.RPC.ChannelAcceptor()
  413. go acceptChannel(ht.T, zeroConf, acceptStream)
  414. // Open a private channel, optionally specifying a channel-type.
  415. params := lntest.OpenChannelParams{
  416. Amt: chanAmt,
  417. Private: private,
  418. CommitmentType: lnrpc.CommitmentType_ANCHORS,
  419. ZeroConf: zeroConf,
  420. ScidAlias: scidAliasType,
  421. PushAmt: chanAmt / 2,
  422. }
  423. fundingPoint2 := ht.OpenChannelNoAnnounce(carol, dave, params)
  424. // Remove the ChannelAcceptor.
  425. cancel()
  426. // Carol will now update the channel edge policy for her channel with
  427. // Dave.
  428. baseFeeMSat := 33000
  429. feeRate := int64(5)
  430. timeLockDelta := uint32(chainreg.DefaultBitcoinTimeLockDelta)
  431. updateFeeReq := &lnrpc.PolicyUpdateRequest{
  432. BaseFeeMsat: int64(baseFeeMSat),
  433. FeeRate: float64(feeRate),
  434. TimeLockDelta: timeLockDelta,
  435. Scope: &lnrpc.PolicyUpdateRequest_ChanPoint{
  436. ChanPoint: fundingPoint2,
  437. },
  438. }
  439. carol.RPC.UpdateChannelPolicy(updateFeeReq)
  440. expectedPolicy := &lnrpc.RoutingPolicy{
  441. FeeBaseMsat: int64(baseFeeMSat),
  442. FeeRateMilliMsat: testFeeBase * feeRate,
  443. TimeLockDelta: timeLockDelta,
  444. MinHtlc: 1000, // default value
  445. MaxHtlcMsat: lntest.CalculateMaxHtlc(chanAmt),
  446. }
  447. // Assert that Dave receives Carol's policy update.
  448. ht.AssertChannelPolicyUpdate(
  449. dave, carol, expectedPolicy, fundingPoint2, true,
  450. )
  451. // Have Dave also update his policy.
  452. baseFeeMSat = 15000
  453. feeRate = int64(4)
  454. updateFeeReq = &lnrpc.PolicyUpdateRequest{
  455. BaseFeeMsat: int64(baseFeeMSat),
  456. FeeRate: float64(feeRate),
  457. TimeLockDelta: timeLockDelta,
  458. Scope: &lnrpc.PolicyUpdateRequest_ChanPoint{
  459. ChanPoint: fundingPoint2,
  460. },
  461. }
  462. dave.RPC.UpdateChannelPolicy(updateFeeReq)
  463. expectedPolicy = &lnrpc.RoutingPolicy{
  464. FeeBaseMsat: int64(baseFeeMSat),
  465. FeeRateMilliMsat: testFeeBase * feeRate,
  466. TimeLockDelta: timeLockDelta,
  467. MinHtlc: 1000,
  468. MaxHtlcMsat: lntest.CalculateMaxHtlc(chanAmt),
  469. }
  470. // Assert that Carol receives Dave's policy update.
  471. ht.AssertChannelPolicyUpdate(
  472. carol, dave, expectedPolicy, fundingPoint2, true,
  473. )
  474. // Assert that if Dave disables the channel, Carol sees it.
  475. disableReq := &routerrpc.UpdateChanStatusRequest{
  476. ChanPoint: fundingPoint2,
  477. Action: routerrpc.ChanStatusAction_DISABLE,
  478. }
  479. dave.RPC.UpdateChanStatus(disableReq)
  480. expectedPolicy.Disabled = true
  481. ht.AssertChannelPolicyUpdate(
  482. carol, dave, expectedPolicy, fundingPoint2, true,
  483. )
  484. // Assert that if Dave enables the channel, Carol sees it.
  485. enableReq := &routerrpc.UpdateChanStatusRequest{
  486. ChanPoint: fundingPoint2,
  487. Action: routerrpc.ChanStatusAction_ENABLE,
  488. }
  489. dave.RPC.UpdateChanStatus(enableReq)
  490. expectedPolicy.Disabled = false
  491. ht.AssertChannelPolicyUpdate(
  492. carol, dave, expectedPolicy, fundingPoint2, true,
  493. )
  494. // Create an invoice for Carol to pay.
  495. invoiceParams := &lnrpc.Invoice{
  496. Value: int64(10_000),
  497. Private: true,
  498. }
  499. daveInvoiceResp := dave.RPC.AddInvoice(invoiceParams)
  500. // Carol will attempt to send Dave an HTLC.
  501. payReqs := []string{daveInvoiceResp.PaymentRequest}
  502. ht.CompletePaymentRequests(carol, payReqs)
  503. // Now Eve will create an invoice that Dave will pay.
  504. eveInvoiceResp := eve.RPC.AddInvoice(invoiceParams)
  505. payReqs = []string{eveInvoiceResp.PaymentRequest}
  506. ht.CompletePaymentRequests(dave, payReqs)
  507. // If this is a public channel, it won't be included in the hop hints,
  508. // so we'll mine enough for 6 confs here. We only expect a tx in the
  509. // mempool for the zero-conf case.
  510. if !private {
  511. var expectTx int
  512. if zeroConf {
  513. expectTx = 1
  514. }
  515. ht.MineBlocksAndAssertNumTxes(6, expectTx)
  516. // Sleep here so that the edge can be deleted and re-inserted.
  517. // This is necessary since the edge may have a policy for the
  518. // peer that is "correct" but has an invalid signature from the
  519. // PoV of BOLT#7.
  520. //
  521. // TODO(yy): further investigate this sleep.
  522. time.Sleep(time.Second * 5)
  523. }
  524. // Dave creates an invoice that Eve will pay.
  525. daveInvoiceResp2 := dave.RPC.AddInvoice(invoiceParams)
  526. // Carol then updates the channel policy again.
  527. feeRate = int64(2)
  528. updateFeeReq = &lnrpc.PolicyUpdateRequest{
  529. BaseFeeMsat: int64(baseFeeMSat),
  530. FeeRate: float64(feeRate),
  531. TimeLockDelta: timeLockDelta,
  532. Scope: &lnrpc.PolicyUpdateRequest_ChanPoint{
  533. ChanPoint: fundingPoint2,
  534. },
  535. }
  536. carol.RPC.UpdateChannelPolicy(updateFeeReq)
  537. expectedPolicy = &lnrpc.RoutingPolicy{
  538. FeeBaseMsat: int64(baseFeeMSat),
  539. FeeRateMilliMsat: testFeeBase * feeRate,
  540. TimeLockDelta: timeLockDelta,
  541. MinHtlc: 1000,
  542. MaxHtlcMsat: lntest.CalculateMaxHtlc(chanAmt),
  543. }
  544. // Assert Dave receives Carol's policy update.
  545. ht.AssertChannelPolicyUpdate(
  546. dave, carol, expectedPolicy, fundingPoint2, true,
  547. )
  548. // If the channel is public, check that Eve receives Carol's policy
  549. // update.
  550. if !private {
  551. ht.AssertChannelPolicyUpdate(
  552. eve, carol, expectedPolicy, fundingPoint2, true,
  553. )
  554. }
  555. // Eve will pay Dave's invoice and should use the updated base fee.
  556. payReqs = []string{daveInvoiceResp2.PaymentRequest}
  557. ht.CompletePaymentRequests(eve, payReqs)
  558. // Eve will issue an invoice that Dave will pay.
  559. eveInvoiceResp2 := eve.RPC.AddInvoice(invoiceParams)
  560. payReqs = []string{eveInvoiceResp2.PaymentRequest}
  561. ht.CompletePaymentRequests(dave, payReqs)
  562. // If this is a private channel, we'll mine 6 blocks here to test the
  563. // funding manager logic that deals with ChannelUpdates. If this is not
  564. // a zero-conf channel, we don't expect a tx in the mempool.
  565. if private {
  566. var expectTx int
  567. if zeroConf {
  568. expectTx = 1
  569. }
  570. ht.MineBlocksAndAssertNumTxes(6, expectTx)
  571. }
  572. // Dave will issue an invoice and Eve will pay it.
  573. daveInvoiceResp3 := dave.RPC.AddInvoice(invoiceParams)
  574. payReqs = []string{daveInvoiceResp3.PaymentRequest}
  575. ht.CompletePaymentRequests(eve, payReqs)
  576. // Carol will disable the channel, assert that Dave sees it and Eve as
  577. // well if the channel is public.
  578. carol.RPC.UpdateChanStatus(disableReq)
  579. expectedPolicy.Disabled = true
  580. ht.AssertChannelPolicyUpdate(
  581. dave, carol, expectedPolicy, fundingPoint2, true,
  582. )
  583. if !private {
  584. ht.AssertChannelPolicyUpdate(
  585. eve, carol, expectedPolicy, fundingPoint2, true,
  586. )
  587. }
  588. // Carol will enable the channel, assert the same as above.
  589. carol.RPC.UpdateChanStatus(enableReq)
  590. expectedPolicy.Disabled = false
  591. ht.AssertChannelPolicyUpdate(
  592. dave, carol, expectedPolicy, fundingPoint2, true,
  593. )
  594. if !private {
  595. ht.AssertChannelPolicyUpdate(
  596. eve, carol, expectedPolicy, fundingPoint2, true,
  597. )
  598. }
  599. // Dave will issue an invoice and Eve should pay it after Carol updates
  600. // her channel policy.
  601. daveInvoiceResp4 := dave.RPC.AddInvoice(invoiceParams)
  602. feeRate = int64(3)
  603. updateFeeReq = &lnrpc.PolicyUpdateRequest{
  604. BaseFeeMsat: int64(baseFeeMSat),
  605. FeeRate: float64(feeRate),
  606. TimeLockDelta: timeLockDelta,
  607. Scope: &lnrpc.PolicyUpdateRequest_ChanPoint{
  608. ChanPoint: fundingPoint2,
  609. },
  610. }
  611. carol.RPC.UpdateChannelPolicy(updateFeeReq)
  612. expectedPolicy = &lnrpc.RoutingPolicy{
  613. FeeBaseMsat: int64(baseFeeMSat),
  614. FeeRateMilliMsat: testFeeBase * feeRate,
  615. TimeLockDelta: timeLockDelta,
  616. MinHtlc: 1000,
  617. MaxHtlcMsat: lntest.CalculateMaxHtlc(chanAmt),
  618. }
  619. // Assert Dave and optionally Eve receives Carol's update.
  620. ht.AssertChannelPolicyUpdate(
  621. dave, carol, expectedPolicy, fundingPoint2, true,
  622. )
  623. if !private {
  624. ht.AssertChannelPolicyUpdate(
  625. eve, carol, expectedPolicy, fundingPoint2, true,
  626. )
  627. }
  628. payReqs = []string{daveInvoiceResp4.PaymentRequest}
  629. ht.CompletePaymentRequests(eve, payReqs)
  630. }
  631. // testOptionScidUpgrade tests that toggling the option-scid-alias feature bit
  632. // correctly upgrades existing channels.
  633. func testOptionScidUpgrade(ht *lntest.HarnessTest) {
  634. bob := ht.Bob
  635. // Start carol with anchors only.
  636. carolArgs := []string{
  637. "--protocol.anchors",
  638. }
  639. carol := ht.NewNode("carol", carolArgs)
  640. // Start dave with anchors + scid-alias.
  641. daveArgs := []string{
  642. "--protocol.anchors",
  643. "--protocol.option-scid-alias",
  644. }
  645. dave := ht.NewNode("dave", daveArgs)
  646. // Give carol some coins.
  647. ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
  648. // Ensure carol and are connected.
  649. ht.EnsureConnected(carol, dave)
  650. chanAmt := btcutil.Amount(1_000_000)
  651. p := lntest.OpenChannelParams{
  652. Amt: chanAmt,
  653. PushAmt: chanAmt / 2,
  654. Private: true,
  655. }
  656. ht.OpenChannel(carol, dave, p)
  657. // Bob will open a channel to Carol now.
  658. ht.EnsureConnected(bob, carol)
  659. p = lntest.OpenChannelParams{
  660. Amt: chanAmt,
  661. }
  662. fundingPoint2 := ht.OpenChannel(bob, carol, p)
  663. // Make sure Dave knows this channel.
  664. ht.AssertTopologyChannelOpen(dave, fundingPoint2)
  665. // Carol will now set the option-scid-alias feature bit and restart.
  666. carolArgs = append(carolArgs, "--protocol.option-scid-alias")
  667. ht.RestartNodeWithExtraArgs(carol, carolArgs)
  668. // Dave will create an invoice for Carol to pay, it should contain an
  669. // alias in the hop hints.
  670. daveParams := &lnrpc.Invoice{
  671. Value: int64(10_000),
  672. Private: true,
  673. }
  674. var daveInvoice *lnrpc.AddInvoiceResponse
  675. var startingAlias lnwire.ShortChannelID
  676. startingAlias.BlockHeight = 16_000_000
  677. // TODO(yy): Carol and Dave will attempt to connect to each other
  678. // during restart. However, due to the race condition in peer
  679. // connection, they may both fail. Thus we need to ensure the
  680. // connection here. Once the race is fixed, we can remove this line.
  681. ht.EnsureConnected(dave, carol)
  682. err := wait.NoError(func() error {
  683. invoiceResp := dave.RPC.AddInvoice(daveParams)
  684. decodedReq := dave.RPC.DecodePayReq(invoiceResp.PaymentRequest)
  685. if len(decodedReq.RouteHints) != 1 {
  686. return fmt.Errorf("expected 1 route hint, got %v",
  687. decodedReq.RouteHints)
  688. }
  689. if len(decodedReq.RouteHints[0].HopHints) != 1 {
  690. return fmt.Errorf("expected 1 hop hint, got %v",
  691. len(decodedReq.RouteHints[0].HopHints))
  692. }
  693. hopHint := decodedReq.RouteHints[0].HopHints[0].ChanId
  694. if startingAlias.ToUint64() == hopHint {
  695. daveInvoice = invoiceResp
  696. return nil
  697. }
  698. return fmt.Errorf("unmatched alias, expected %v, got %v",
  699. startingAlias.ToUint64(), hopHint)
  700. }, defaultTimeout)
  701. require.NoError(ht, err)
  702. // Carol should be able to pay it.
  703. ht.CompletePaymentRequests(carol, []string{daveInvoice.PaymentRequest})
  704. // TODO(yy): remove this connection once the following bug is fixed.
  705. // When Carol restarts, she will try to make a persistent connection to
  706. // Bob. Meanwhile, Bob will also make a conn request as he notices the
  707. // connection is broken. If they make these conn requests at the same
  708. // time, they both have an outbound conn request, and will close the
  709. // inbound conn they receives, which ends up in no conn.
  710. ht.EnsureConnected(bob, carol)
  711. daveInvoice2 := dave.RPC.AddInvoice(daveParams)
  712. ht.CompletePaymentRequests(bob, []string{daveInvoice2.PaymentRequest})
  713. // Close standby node's channels.
  714. ht.CloseChannel(bob, fundingPoint2)
  715. }
  716. // acceptChannel is used to accept a single channel that comes across. This
  717. // should be run in a goroutine and is used to test nodes with the zero-conf
  718. // feature bit.
  719. func acceptChannel(t *testing.T, zeroConf bool, stream rpc.AcceptorClient) {
  720. t.Helper()
  721. req, err := stream.Recv()
  722. require.NoError(t, err)
  723. resp := &lnrpc.ChannelAcceptResponse{
  724. Accept: true,
  725. PendingChanId: req.PendingChanId,
  726. ZeroConf: zeroConf,
  727. }
  728. err = stream.Send(resp)
  729. require.NoError(t, err)
  730. }
  731. // testZeroConfReorg tests that a reorg does not cause a zero-conf channel to
  732. // be deleted from the channel graph. This was previously the case due to logic
  733. // in the function DisconnectBlockAtHeight.
  734. func testZeroConfReorg(ht *lntest.HarnessTest) {
  735. if ht.IsNeutrinoBackend() {
  736. ht.Skipf("skipping zero-conf reorg test for neutrino backend")
  737. }
  738. // Since zero-conf is opt in, the harness nodes provided won't be able
  739. // to open zero-conf channels. In that case, we just spin up new nodes.
  740. zeroConfArgs := []string{
  741. "--protocol.option-scid-alias",
  742. "--protocol.zero-conf",
  743. "--protocol.anchors",
  744. }
  745. carol := ht.NewNode("Carol", zeroConfArgs)
  746. // Spin-up Dave so Carol can open a zero-conf channel to him.
  747. dave := ht.NewNode("Dave", zeroConfArgs)
  748. // We'll give Carol some coins in order to fund the channel.
  749. ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
  750. // Ensure that both Carol and Dave are connected.
  751. ht.EnsureConnected(carol, dave)
  752. // Setup a ChannelAcceptor for Dave.
  753. acceptStream, cancel := dave.RPC.ChannelAcceptor()
  754. go acceptChannel(ht.T, true, acceptStream)
  755. // Open a private zero-conf anchors channel of 1M satoshis.
  756. params := lntest.OpenChannelParams{
  757. Amt: btcutil.Amount(1_000_000),
  758. CommitmentType: lnrpc.CommitmentType_ANCHORS,
  759. ZeroConf: true,
  760. }
  761. _ = ht.OpenChannelNoAnnounce(carol, dave, params)
  762. // Remove the ChannelAcceptor.
  763. cancel()
  764. // Attempt to send a 10K satoshi payment from Carol to Dave. This
  765. // requires that the edge exists in the graph.
  766. daveInvoiceParams := &lnrpc.Invoice{
  767. Value: int64(10_000),
  768. }
  769. daveInvoiceResp := dave.RPC.AddInvoice(daveInvoiceParams)
  770. payReqs := []string{daveInvoiceResp.PaymentRequest}
  771. ht.CompletePaymentRequests(carol, payReqs)
  772. // We will now attempt to query for the alias SCID in Carol's graph.
  773. // We will query for the starting alias, which is exported by the
  774. // aliasmgr package.
  775. carol.RPC.GetChanInfo(&lnrpc.ChanInfoRequest{
  776. ChanId: aliasmgr.StartingAlias.ToUint64(),
  777. })
  778. // Now we will trigger a reorg and we'll assert that the edge still
  779. // exists in the graph.
  780. //
  781. // First, we'll setup a new miner that we can use to cause a reorg.
  782. tempMiner := ht.Miner.SpawnTempMiner()
  783. // We now cause a fork, by letting our original miner mine 1 block and
  784. // our new miner will mine 2. We also expect the funding transition to
  785. // be mined.
  786. ht.MineBlocksAndAssertNumTxes(1, 1)
  787. tempMiner.MineEmptyBlocks(2)
  788. // Ensure the temp miner is one block ahead.
  789. ht.Miner.AssertMinerBlockHeightDelta(tempMiner, 1)
  790. // Wait for Carol to sync to the original miner's chain.
  791. _, minerHeight := ht.Miner.GetBestBlock()
  792. ht.WaitForNodeBlockHeight(carol, minerHeight)
  793. // Now we'll disconnect Carol's chain backend from the original miner
  794. // so that we can connect the two miners together and let the original
  795. // miner sync to the temp miner's chain.
  796. ht.DisconnectMiner()
  797. // Connecting to the temporary miner should cause the original miner to
  798. // reorg to the longer chain.
  799. ht.Miner.ConnectMiner(tempMiner)
  800. // They should now be on the same chain.
  801. ht.Miner.AssertMinerBlockHeightDelta(tempMiner, 0)
  802. // Now we disconnect the two miners and reconnect our original chain
  803. // backend.
  804. ht.Miner.DisconnectMiner(tempMiner)
  805. ht.ConnectMiner()
  806. // This should have caused a reorg and Carol should sync to the new
  807. // chain.
  808. _, tempMinerHeight := tempMiner.GetBestBlock()
  809. ht.WaitForNodeBlockHeight(carol, tempMinerHeight)
  810. // Make sure all active nodes are synced.
  811. ht.AssertActiveNodesSynced()
  812. // Carol should have the channel once synced.
  813. carol.RPC.GetChanInfo(&lnrpc.ChanInfoRequest{
  814. ChanId: aliasmgr.StartingAlias.ToUint64(),
  815. })
  816. // Mine the zero-conf funding transaction so the test doesn't fail.
  817. ht.MineBlocksAndAssertNumTxes(1, 1)
  818. }