lntemp+itest: refactor node restart process
This commit refactors how the node restart is done. It removes the usage of `HasSeed` and replaces it with `SkipUnlock` for clarity.
This commit is contained in:
5 files changed
+80
-67
No files matched your search
+29
-6
@@ -486,13 +486,33 @@ func (h *HarnessTest) SuspendNode(node *node.HarnessNode) func() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RestartNode restarts a given node and asserts.
|
// RestartNode restarts a given node, unlocks it and asserts it's successfully
|
||||||
func (h *HarnessTest) RestartNode(hn *node.HarnessNode,
|
// started.
|
||||||
|
func (h *HarnessTest) RestartNode(hn *node.HarnessNode) {
|
||||||
|
err := h.manager.restartNode(h.runCtx, hn, nil)
|
||||||
|
require.NoErrorf(h, err, "failed to restart node %s", hn.Name())
|
||||||
|
|
||||||
|
err = h.manager.unlockNode(hn)
|
||||||
|
require.NoErrorf(h, err, "failed to unlock node %s", hn.Name())
|
||||||
|
|
||||||
|
if !hn.Cfg.SkipUnlock {
|
||||||
|
// Give the node some time to catch up with the chain before we
|
||||||
|
// continue with the tests.
|
||||||
|
h.WaitForBlockchainSync(hn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RestartNodeWithChanBackups restarts a given node with the specified channel
|
||||||
|
// backups.
|
||||||
|
func (h *HarnessTest) RestartNodeWithChanBackups(hn *node.HarnessNode,
|
||||||
chanBackups ...*lnrpc.ChanBackupSnapshot) {
|
chanBackups ...*lnrpc.ChanBackupSnapshot) {
|
||||||
|
|
||||||
err := h.manager.restartNode(h.runCtx, hn, nil, chanBackups...)
|
err := h.manager.restartNode(h.runCtx, hn, nil)
|
||||||
require.NoErrorf(h, err, "failed to restart node %s", hn.Name())
|
require.NoErrorf(h, err, "failed to restart node %s", hn.Name())
|
||||||
|
|
||||||
|
err = h.manager.unlockNode(hn, chanBackups...)
|
||||||
|
require.NoErrorf(h, err, "failed to unlock node %s", hn.Name())
|
||||||
|
|
||||||
// Give the node some time to catch up with the chain before we
|
// Give the node some time to catch up with the chain before we
|
||||||
// continue with the tests.
|
// continue with the tests.
|
||||||
h.WaitForBlockchainSync(hn)
|
h.WaitForBlockchainSync(hn)
|
||||||
@@ -503,7 +523,7 @@ func (h *HarnessTest) RestartNodeWithExtraArgs(hn *node.HarnessNode,
|
|||||||
extraArgs []string) {
|
extraArgs []string) {
|
||||||
|
|
||||||
hn.SetExtraArgs(extraArgs)
|
hn.SetExtraArgs(extraArgs)
|
||||||
h.RestartNode(hn, nil)
|
h.RestartNode(hn)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewNodeWithSeed fully initializes a new HarnessNode after creating a fresh
|
// NewNodeWithSeed fully initializes a new HarnessNode after creating a fresh
|
||||||
@@ -538,7 +558,7 @@ func (h *HarnessTest) newNodeWithSeed(name string,
|
|||||||
|
|
||||||
// Start the node with seed only, which will only create the `State`
|
// Start the node with seed only, which will only create the `State`
|
||||||
// and `WalletUnlocker` clients.
|
// and `WalletUnlocker` clients.
|
||||||
err = node.StartWithSeed(h.runCtx)
|
err = node.StartWithNoAuth(h.runCtx)
|
||||||
require.NoErrorf(h, err, "failed to start node %s", node.Name())
|
require.NoErrorf(h, err, "failed to start node %s", node.Name())
|
||||||
|
|
||||||
// Generate a new seed.
|
// Generate a new seed.
|
||||||
@@ -581,7 +601,7 @@ func (h *HarnessTest) RestoreNodeWithSeed(name string, extraArgs []string,
|
|||||||
|
|
||||||
// Start the node with seed only, which will only create the `State`
|
// Start the node with seed only, which will only create the `State`
|
||||||
// and `WalletUnlocker` clients.
|
// and `WalletUnlocker` clients.
|
||||||
err = node.StartWithSeed(h.runCtx)
|
err = node.StartWithNoAuth(h.runCtx)
|
||||||
require.NoErrorf(h, err, "failed to start node %s", node.Name())
|
require.NoErrorf(h, err, "failed to start node %s", node.Name())
|
||||||
|
|
||||||
// Create the wallet.
|
// Create the wallet.
|
||||||
@@ -1344,6 +1364,9 @@ func (h *HarnessTest) RestartNodeAndRestoreDB(hn *node.HarnessNode) {
|
|||||||
err := h.manager.restartNode(h.runCtx, hn, cb)
|
err := h.manager.restartNode(h.runCtx, hn, cb)
|
||||||
require.NoErrorf(h, err, "failed to restart node %s", hn.Name())
|
require.NoErrorf(h, err, "failed to restart node %s", hn.Name())
|
||||||
|
|
||||||
|
err = h.manager.unlockNode(hn)
|
||||||
|
require.NoErrorf(h, err, "failed to unlock node %s", hn.Name())
|
||||||
|
|
||||||
// Give the node some time to catch up with the chain before we
|
// Give the node some time to catch up with the chain before we
|
||||||
// continue with the tests.
|
// continue with the tests.
|
||||||
h.WaitForBlockchainSync(hn)
|
h.WaitForBlockchainSync(hn)
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ func (nm *nodeManager) nextNodeID() uint32 {
|
|||||||
// node can be used immediately. Otherwise, the node will require an additional
|
// node can be used immediately. Otherwise, the node will require an additional
|
||||||
// initialization phase where the wallet is either created or restored.
|
// initialization phase where the wallet is either created or restored.
|
||||||
func (nm *nodeManager) newNode(t *testing.T, name string, extraArgs []string,
|
func (nm *nodeManager) newNode(t *testing.T, name string, extraArgs []string,
|
||||||
password []byte, useSeed bool) (*node.HarnessNode, error) {
|
password []byte, noAuth bool) (*node.HarnessNode, error) {
|
||||||
|
|
||||||
cfg := &node.BaseNodeConfig{
|
cfg := &node.BaseNodeConfig{
|
||||||
Name: name,
|
Name: name,
|
||||||
@@ -84,7 +84,7 @@ func (nm *nodeManager) newNode(t *testing.T, name string, extraArgs []string,
|
|||||||
NodeID: nm.nextNodeID(),
|
NodeID: nm.nextNodeID(),
|
||||||
LndBinary: nm.lndBinary,
|
LndBinary: nm.lndBinary,
|
||||||
NetParams: harnessNetParams,
|
NetParams: harnessNetParams,
|
||||||
HasSeed: useSeed,
|
SkipUnlock: noAuth,
|
||||||
}
|
}
|
||||||
|
|
||||||
node, err := node.NewHarnessNode(t, cfg)
|
node, err := node.NewHarnessNode(t, cfg)
|
||||||
@@ -125,56 +125,11 @@ func (nm *nodeManager) shutdownNode(node *node.HarnessNode) error {
|
|||||||
// the connection attempt is successful. If the callback parameter is non-nil,
|
// the connection attempt is successful. If the callback parameter is non-nil,
|
||||||
// then the function will be executed after the node shuts down, but *before*
|
// then the function will be executed after the node shuts down, but *before*
|
||||||
// the process has been started up again.
|
// the process has been started up again.
|
||||||
//
|
func (nm *nodeManager) restartNode(ctxt context.Context,
|
||||||
// This method can be useful when testing edge cases such as a node broadcast
|
hn *node.HarnessNode, callback func() error) error {
|
||||||
// and invalidated prior state, or persistent state recovery, simulating node
|
|
||||||
// crashes, etc. Additionally, each time the node is restarted, the caller can
|
|
||||||
// pass a set of SCBs to pass in via the Unlock method allowing them to restore
|
|
||||||
// channels during restart.
|
|
||||||
func (nm *nodeManager) restartNode(ctxt context.Context, node *node.HarnessNode,
|
|
||||||
callback func() error, chanBackups ...*lnrpc.ChanBackupSnapshot) error {
|
|
||||||
|
|
||||||
err := nm.restartNodeNoUnlock(ctxt, node, callback)
|
// Stop the node.
|
||||||
if err != nil {
|
if err := hn.Stop(); err != nil {
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the node doesn't have a password set, then we can exit here as we
|
|
||||||
// don't need to unlock it.
|
|
||||||
if len(node.Cfg.Password) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, we'll unlock the wallet, then complete the final steps
|
|
||||||
// for the node initialization process.
|
|
||||||
unlockReq := &lnrpc.UnlockWalletRequest{
|
|
||||||
WalletPassword: node.Cfg.Password,
|
|
||||||
}
|
|
||||||
if len(chanBackups) != 0 {
|
|
||||||
unlockReq.ChannelBackups = chanBackups[0]
|
|
||||||
unlockReq.RecoveryWindow = 100
|
|
||||||
}
|
|
||||||
|
|
||||||
err = wait.NoError(func() error {
|
|
||||||
return node.Unlock(unlockReq)
|
|
||||||
}, DefaultTimeout)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("%s: failed to unlock: %w", node.Name(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// restartNodeNoUnlock attempts to restart a lightning node by shutting it down
|
|
||||||
// cleanly, then restarting the process. In case the node was setup with a
|
|
||||||
// seed, it will be left in the unlocked state. This function is fully
|
|
||||||
// blocking. If the callback parameter is non-nil, then the function will be
|
|
||||||
// executed after the node shuts down, but *before* the process has been
|
|
||||||
// started up again.
|
|
||||||
func (nm *nodeManager) restartNodeNoUnlock(ctxt context.Context,
|
|
||||||
node *node.HarnessNode, callback func() error) error {
|
|
||||||
|
|
||||||
if err := node.Stop(); err != nil {
|
|
||||||
return fmt.Errorf("restart node got error: %w", err)
|
return fmt.Errorf("restart node got error: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,11 +139,45 @@ func (nm *nodeManager) restartNodeNoUnlock(ctxt context.Context,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if node.Cfg.HasSeed {
|
// Start the node without unlocking the wallet.
|
||||||
return node.StartWithSeed(ctxt)
|
if hn.Cfg.SkipUnlock {
|
||||||
|
return hn.StartWithNoAuth(ctxt)
|
||||||
}
|
}
|
||||||
|
|
||||||
return node.Start(ctxt)
|
return hn.Start(ctxt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// unlockNode unlocks the node's wallet if the password is configured.
|
||||||
|
// Additionally, each time the node is unlocked, the caller can pass a set of
|
||||||
|
// SCBs to pass in via the Unlock method allowing them to restore channels
|
||||||
|
// during restart.
|
||||||
|
func (nm *nodeManager) unlockNode(hn *node.HarnessNode,
|
||||||
|
chanBackups ...*lnrpc.ChanBackupSnapshot) error {
|
||||||
|
|
||||||
|
// If the node doesn't have a password set, then we can exit here as we
|
||||||
|
// don't need to unlock it.
|
||||||
|
if len(hn.Cfg.Password) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, we'll unlock the wallet, then complete the final steps
|
||||||
|
// for the node initialization process.
|
||||||
|
unlockReq := &lnrpc.UnlockWalletRequest{
|
||||||
|
WalletPassword: hn.Cfg.Password,
|
||||||
|
}
|
||||||
|
if len(chanBackups) != 0 {
|
||||||
|
unlockReq.ChannelBackups = chanBackups[0]
|
||||||
|
unlockReq.RecoveryWindow = 100
|
||||||
|
}
|
||||||
|
|
||||||
|
err := wait.NoError(func() error {
|
||||||
|
return hn.Unlock(unlockReq)
|
||||||
|
}, DefaultTimeout)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("%s: failed to unlock: %w", hn.Name(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// initWalletAndNode will unlock the node's wallet and finish setting up the
|
// initWalletAndNode will unlock the node's wallet and finish setting up the
|
||||||
|
|||||||
@@ -63,8 +63,8 @@ type BaseNodeConfig struct {
|
|||||||
ReadMacPath string
|
ReadMacPath string
|
||||||
InvoiceMacPath string
|
InvoiceMacPath string
|
||||||
|
|
||||||
HasSeed bool
|
SkipUnlock bool
|
||||||
Password []byte
|
Password []byte
|
||||||
|
|
||||||
P2PPort int
|
P2PPort int
|
||||||
RPCPort int
|
RPCPort int
|
||||||
@@ -190,7 +190,7 @@ func (cfg *BaseNodeConfig) GenArgs() []string {
|
|||||||
}
|
}
|
||||||
args = append(args, nodeArgs...)
|
args = append(args, nodeArgs...)
|
||||||
|
|
||||||
if !cfg.HasSeed {
|
if cfg.Password == nil {
|
||||||
args = append(args, "--noseedbackup")
|
args = append(args, "--noseedbackup")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -387,12 +387,12 @@ func (hn *HarnessNode) StartLndCmd(ctxb context.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// StartWithSeed will start the lnd process, creates the grpc connection
|
// StartWithNoAuth will start the lnd process, creates the grpc connection
|
||||||
// without macaroon auth, and waits until the server is reported as waiting to
|
// without macaroon auth, and waits until the server is reported as waiting to
|
||||||
// start.
|
// start.
|
||||||
//
|
//
|
||||||
// NOTE: caller needs to take extra step to create and unlock the wallet.
|
// NOTE: caller needs to take extra step to create and unlock the wallet.
|
||||||
func (hn *HarnessNode) StartWithSeed(ctxt context.Context) error {
|
func (hn *HarnessNode) StartWithNoAuth(ctxt context.Context) error {
|
||||||
// Start lnd process and prepare logs.
|
// Start lnd process and prepare logs.
|
||||||
if err := hn.StartLndCmd(ctxt); err != nil {
|
if err := hn.StartLndCmd(ctxt); err != nil {
|
||||||
return fmt.Errorf("start lnd error: %w", err)
|
return fmt.Errorf("start lnd error: %w", err)
|
||||||
|
|||||||
@@ -349,8 +349,9 @@ func testChannelBackupRestoreBasic(ht *lntemp.HarnessTest) {
|
|||||||
"", revocationWindow, nil,
|
"", revocationWindow, nil,
|
||||||
copyPorts(oldNode),
|
copyPorts(oldNode),
|
||||||
)
|
)
|
||||||
|
st.RestartNodeWithChanBackups(
|
||||||
st.RestartNode(newNode, backupSnapshot)
|
newNode, backupSnapshot,
|
||||||
|
)
|
||||||
|
|
||||||
return newNode
|
return newNode
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user