From 8a4d2741a38069bf904f13b452c79315a84aa791 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Tue, 9 Aug 2022 15:18:39 +0800 Subject: [PATCH] lntemp+itest: refactor `testStatelessInit` --- lntemp/harness.go | 6 ++ lntemp/node/harness_node.go | 13 ++++ lntemp/rpc/wallet_unlocker.go | 14 +++++ lntest/itest/list_on_test.go | 4 ++ lntest/itest/lnd_macaroons_test.go | 90 ++++++++++----------------- lntest/itest/lnd_test_list_on_test.go | 4 -- 6 files changed, 71 insertions(+), 60 deletions(-) diff --git a/lntemp/harness.go b/lntemp/harness.go index 8acbf4a42..75454c105 100644 --- a/lntemp/harness.go +++ b/lntemp/harness.go @@ -502,6 +502,12 @@ func (h *HarnessTest) RestartNode(hn *node.HarnessNode) { } } +// RestartNodeNoUnlock restarts a given node without unlocking its wallet. +func (h *HarnessTest) RestartNodeNoUnlock(hn *node.HarnessNode) { + err := h.manager.restartNode(h.runCtx, hn, nil) + require.NoErrorf(h, err, "failed to restart node %s", hn.Name()) +} + // RestartNodeWithChanBackups restarts a given node with the specified channel // backups. func (h *HarnessTest) RestartNodeWithChanBackups(hn *node.HarnessNode, diff --git a/lntemp/node/harness_node.go b/lntemp/node/harness_node.go index 230be2a68..1dc484bed 100644 --- a/lntemp/node/harness_node.go +++ b/lntemp/node/harness_node.go @@ -488,6 +488,19 @@ func (hn *HarnessNode) InitNode(macBytes []byte) error { return hn.initLightningClient() } +// InitChangePassword initializes a harness node by passing the change password +// request via RPC. After the request is submitted, this method will block until +// a macaroon-authenticated RPC connection can be established to the harness +// node. Once established, the new connection is used to initialize the +// RPC clients and subscribes the HarnessNode to topology changes. +func (hn *HarnessNode) ChangePasswordAndInit( + req *lnrpc.ChangePasswordRequest) ( + *lnrpc.ChangePasswordResponse, error) { + + response := hn.RPC.ChangePassword(req) + return response, hn.InitNode(response.AdminMacaroon) +} + // waitTillServerState makes a subscription to the server's state change and // blocks until the server is in the targeted state. func (hn *HarnessNode) waitTillServerState( diff --git a/lntemp/rpc/wallet_unlocker.go b/lntemp/rpc/wallet_unlocker.go index 726abef85..c4fb60c86 100644 --- a/lntemp/rpc/wallet_unlocker.go +++ b/lntemp/rpc/wallet_unlocker.go @@ -48,3 +48,17 @@ func (h *HarnessRPC) GenSeed(req *lnrpc.GenSeedRequest) *lnrpc.GenSeedResponse { return resp } + +// ChangePassword makes a RPC request to WalletUnlocker and asserts there's no +// error. +func (h *HarnessRPC) ChangePassword( + req *lnrpc.ChangePasswordRequest) *lnrpc.ChangePasswordResponse { + + ctxt, cancel := context.WithTimeout(h.runCtx, DefaultTimeout) + defer cancel() + + resp, err := h.WalletUnlocker.ChangePassword(ctxt, req) + h.NoError(err, "ChangePassword") + + return resp +} diff --git a/lntest/itest/list_on_test.go b/lntest/itest/list_on_test.go index 2bbabf2ef..514edba19 100644 --- a/lntest/itest/list_on_test.go +++ b/lntest/itest/list_on_test.go @@ -357,4 +357,8 @@ var allTestCasesTemp = []*lntemp.TestCase{ Name: "delete macaroon id", TestFunc: testDeleteMacaroonID, }, + { + Name: "stateless init", + TestFunc: testStatelessInit, + }, } diff --git a/lntest/itest/lnd_macaroons_test.go b/lntest/itest/lnd_macaroons_test.go index 3622c6ba2..01d576f8f 100644 --- a/lntest/itest/lnd_macaroons_test.go +++ b/lntest/itest/lnd_macaroons_test.go @@ -1,7 +1,6 @@ package itest import ( - "bytes" "context" "encoding/hex" "os" @@ -14,7 +13,6 @@ import ( "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lntemp" "github.com/lightningnetwork/lnd/lntemp/node" - "github.com/lightningnetwork/lnd/lntest" "github.com/lightningnetwork/lnd/macaroons" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -612,7 +610,7 @@ func testDeleteMacaroonID(ht *lntemp.HarnessTest) { // does not write any macaroon files to the daemon's file system and returns // the admin macaroon in the response. It then checks that the password // change of the wallet can also happen stateless. -func testStatelessInit(net *lntest.NetworkHarness, t *harnessTest) { +func testStatelessInit(ht *lntemp.HarnessTest) { var ( initPw = []byte("stateless") newPw = []byte("stateless-new") @@ -624,85 +622,79 @@ func testStatelessInit(net *lntest.NetworkHarness, t *harnessTest) { // First, create a new node and request it to initialize stateless. // This should return us the binary serialized admin macaroon that we // can then use for further calls. - carol, _, macBytes, err := net.NewNodeWithSeed( - "Carol", nil, initPw, true, - ) - require.NoError(t.t, err) - if len(macBytes) == 0 { - t.Fatalf("invalid macaroon returned in stateless init") - } + carol, _, macBytes := ht.NewNodeWithSeed("Carol", nil, initPw, true) + require.NotEmpty(ht, macBytes, + "invalid macaroon returned in stateless init") // Now make sure no macaroon files have been created by the node Carol. - _, err = os.Stat(carol.AdminMacPath()) - require.Error(t.t, err) - _, err = os.Stat(carol.ReadMacPath()) - require.Error(t.t, err) - _, err = os.Stat(carol.InvoiceMacPath()) - require.Error(t.t, err) + _, err := os.Stat(carol.Cfg.AdminMacPath) + require.Error(ht, err) + _, err = os.Stat(carol.Cfg.ReadMacPath) + require.Error(ht, err) + _, err = os.Stat(carol.Cfg.InvoiceMacPath) + require.Error(ht, err) // Then check that we can unmarshal the binary serialized macaroon. adminMac := &macaroon.Macaroon{} err = adminMac.UnmarshalBinary(macBytes) - require.NoError(t.t, err) + require.NoError(ht, err) // Find out if we can actually use the macaroon that has been returned // to us for a RPC call. conn, err := carol.ConnectRPCWithMacaroon(adminMac) - require.NoError(t.t, err) + require.NoError(ht, err) defer conn.Close() adminMacClient := lnrpc.NewLightningClient(conn) - ctxt, _ := context.WithTimeout(context.Background(), defaultTimeout) + ctxt, cancel := context.WithTimeout(ht.Context(), defaultTimeout) + defer cancel() res, err := adminMacClient.NewAddress(ctxt, newAddrReq) - require.NoError(t.t, err) + require.NoError(ht, err) if !strings.HasPrefix(res.Address, harnessNetParams.Bech32HRPSegwit) { - t.Fatalf("returned address was not a regtest address") + require.Fail(ht, "returned address was not a regtest address") } // As a second part, shut down the node and then try to change the // password when we start it up again. - if err := net.RestartNodeNoUnlock(carol, nil, true); err != nil { - t.Fatalf("Node restart failed: %v", err) - } + ht.RestartNodeNoUnlock(carol) changePwReq := &lnrpc.ChangePasswordRequest{ CurrentPassword: initPw, NewPassword: newPw, StatelessInit: true, } - response, err := carol.InitChangePassword(changePwReq) - require.NoError(t.t, err) + response, err := carol.ChangePasswordAndInit(changePwReq) + require.NoError(ht, err) // Again, make sure no macaroon files have been created by the node // Carol. - _, err = os.Stat(carol.AdminMacPath()) - require.Error(t.t, err) - _, err = os.Stat(carol.ReadMacPath()) - require.Error(t.t, err) - _, err = os.Stat(carol.InvoiceMacPath()) - require.Error(t.t, err) + _, err = os.Stat(carol.Cfg.AdminMacPath) + require.Error(ht, err) + _, err = os.Stat(carol.Cfg.ReadMacPath) + require.Error(ht, err) + _, err = os.Stat(carol.Cfg.InvoiceMacPath) + require.Error(ht, err) // Then check that we can unmarshal the new binary serialized macaroon // and that it really is a new macaroon. - if err = adminMac.UnmarshalBinary(response.AdminMacaroon); err != nil { - t.Fatalf("unable to unmarshal macaroon: %v", err) - } - if bytes.Equal(response.AdminMacaroon, macBytes) { - t.Fatalf("expected new macaroon to be different") - } + err = adminMac.UnmarshalBinary(response.AdminMacaroon) + require.NoError(ht, err, "unable to unmarshal macaroon") + require.NotEqual(ht, response.AdminMacaroon, macBytes, + "expected new macaroon to be different") // Finally, find out if we can actually use the new macaroon that has // been returned to us for a RPC call. conn2, err := carol.ConnectRPCWithMacaroon(adminMac) - require.NoError(t.t, err) + require.NoError(ht, err) defer conn2.Close() adminMacClient = lnrpc.NewLightningClient(conn2) // Changing the password takes a while, so we use the default timeout // of 30 seconds to wait for the connection to be ready. - ctxt, _ = context.WithTimeout(context.Background(), defaultTimeout) + ctxt, cancel = context.WithTimeout(ht.Context(), defaultTimeout) + defer cancel() res, err = adminMacClient.NewAddress(ctxt, newAddrReq) - require.NoError(t.t, err) + require.NoError(ht, err) if !strings.HasPrefix(res.Address, harnessNetParams.Bech32HRPSegwit) { - t.Fatalf("returned address was not a regtest address") + require.Fail(ht, "returned address was not a regtest address") } } @@ -720,20 +712,6 @@ func readMacaroonFromHex(macHex string) (*macaroon.Macaroon, error) { return mac, nil } -// TODO(yy): remove. -func macaroonClientOld(t *testing.T, testNode *lntest.HarnessNode, - mac *macaroon.Macaroon) (func(), lnrpc.LightningClient) { - - conn, err := testNode.ConnectRPCWithMacaroon(mac) - require.NoError(t, err, "connect to alice") - - cleanup := func() { - err := conn.Close() - require.NoError(t, err, "close") - } - return cleanup, lnrpc.NewLightningClient(conn) -} - func macaroonClient(t *testing.T, testNode *node.HarnessNode, mac *macaroon.Macaroon) (func(), lnrpc.LightningClient) { diff --git a/lntest/itest/lnd_test_list_on_test.go b/lntest/itest/lnd_test_list_on_test.go index ba81d5864..c6da53385 100644 --- a/lntest/itest/lnd_test_list_on_test.go +++ b/lntest/itest/lnd_test_list_on_test.go @@ -92,10 +92,6 @@ var allTestCases = []*testCase{ name: "forward interceptor dedup htlcs", test: testForwardInterceptorDedupHtlc, }, - { - name: "stateless init", - test: testStatelessInit, - }, { name: "wallet import account", test: testWalletImportAccount,