mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-08-03 18:22:25 +02:00
lntemp: support creating node from a seed
This commit is contained in:
@@ -428,6 +428,15 @@ func (h *HarnessTest) Shutdown(node *node.HarnessNode) {
|
|||||||
require.NoErrorf(h, err, "unable to shutdown %v", node.Name())
|
require.NoErrorf(h, err, "unable to shutdown %v", node.Name())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SuspendNode stops the given node and returns a callback that can be used to
|
||||||
|
// start it again.
|
||||||
|
func (h *HarnessTest) SuspendNode(node *node.HarnessNode) func() error {
|
||||||
|
err := node.Stop()
|
||||||
|
require.NoErrorf(h, err, "failed to stop %s", node.Name())
|
||||||
|
|
||||||
|
return func() error { return node.Start(h.runCtx) }
|
||||||
|
}
|
||||||
|
|
||||||
// RestartNode restarts a given node and asserts.
|
// RestartNode restarts a given node and asserts.
|
||||||
func (h *HarnessTest) RestartNode(hn *node.HarnessNode,
|
func (h *HarnessTest) RestartNode(hn *node.HarnessNode,
|
||||||
chanBackups ...*lnrpc.ChanBackupSnapshot) {
|
chanBackups ...*lnrpc.ChanBackupSnapshot) {
|
||||||
@@ -448,6 +457,100 @@ func (h *HarnessTest) RestartNodeWithExtraArgs(hn *node.HarnessNode,
|
|||||||
h.RestartNode(hn, nil)
|
h.RestartNode(hn, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewNodeWithSeed fully initializes a new HarnessNode after creating a fresh
|
||||||
|
// aezeed. The provided password is used as both the aezeed password and the
|
||||||
|
// wallet password. The generated mnemonic is returned along with the
|
||||||
|
// initialized harness node.
|
||||||
|
func (h *HarnessTest) NewNodeWithSeed(name string,
|
||||||
|
extraArgs []string, password []byte,
|
||||||
|
statelessInit bool) (*node.HarnessNode, []string, []byte) {
|
||||||
|
|
||||||
|
// Create a request to generate a new aezeed. The new seed will have
|
||||||
|
// the same password as the internal wallet.
|
||||||
|
req := &lnrpc.GenSeedRequest{
|
||||||
|
AezeedPassphrase: password,
|
||||||
|
SeedEntropy: nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
return h.newNodeWithSeed(name, extraArgs, req, statelessInit)
|
||||||
|
}
|
||||||
|
|
||||||
|
// newNodeWithSeed creates and initializes a new HarnessNode such that it'll be
|
||||||
|
// ready to accept RPC calls. A `GenSeedRequest` is needed to generate the
|
||||||
|
// seed.
|
||||||
|
func (h *HarnessTest) newNodeWithSeed(name string,
|
||||||
|
extraArgs []string, req *lnrpc.GenSeedRequest,
|
||||||
|
statelessInit bool) (*node.HarnessNode, []string, []byte) {
|
||||||
|
|
||||||
|
node, err := h.manager.newNode(
|
||||||
|
h.T, name, extraArgs, req.AezeedPassphrase, true,
|
||||||
|
)
|
||||||
|
require.NoErrorf(h, err, "unable to create new node for %s", name)
|
||||||
|
|
||||||
|
// Start the node with seed only, which will only create the `State`
|
||||||
|
// and `WalletUnlocker` clients.
|
||||||
|
err = node.StartWithSeed(h.runCtx)
|
||||||
|
require.NoErrorf(h, err, "failed to start node %s", node.Name())
|
||||||
|
|
||||||
|
// Generate a new seed.
|
||||||
|
genSeedResp := node.RPC.GenSeed(req)
|
||||||
|
|
||||||
|
// With the seed created, construct the init request to the node,
|
||||||
|
// including the newly generated seed.
|
||||||
|
initReq := &lnrpc.InitWalletRequest{
|
||||||
|
WalletPassword: req.AezeedPassphrase,
|
||||||
|
CipherSeedMnemonic: genSeedResp.CipherSeedMnemonic,
|
||||||
|
AezeedPassphrase: req.AezeedPassphrase,
|
||||||
|
StatelessInit: statelessInit,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pass the init request via rpc to finish unlocking the node. This
|
||||||
|
// will also initialize the macaroon-authenticated LightningClient.
|
||||||
|
adminMac, err := h.manager.initWalletAndNode(node, initReq)
|
||||||
|
require.NoErrorf(h, err, "failed to unlock and init node %s",
|
||||||
|
node.Name())
|
||||||
|
|
||||||
|
// In stateless initialization mode we get a macaroon back that we have
|
||||||
|
// to return to the test, otherwise gRPC calls won't be possible since
|
||||||
|
// there are no macaroon files created in that mode.
|
||||||
|
// In stateful init the admin macaroon will just be nil.
|
||||||
|
return node, genSeedResp.CipherSeedMnemonic, adminMac
|
||||||
|
}
|
||||||
|
|
||||||
|
// RestoreNodeWithSeed fully initializes a HarnessNode using a chosen mnemonic,
|
||||||
|
// password, recovery window, and optionally a set of static channel backups.
|
||||||
|
// After providing the initialization request to unlock the node, this method
|
||||||
|
// will finish initializing the LightningClient such that the HarnessNode can
|
||||||
|
// be used for regular rpc operations.
|
||||||
|
func (h *HarnessTest) RestoreNodeWithSeed(name string, extraArgs []string,
|
||||||
|
password []byte, mnemonic []string, rootKey string,
|
||||||
|
recoveryWindow int32, chanBackups *lnrpc.ChanBackupSnapshot,
|
||||||
|
opts ...node.Option) *node.HarnessNode {
|
||||||
|
|
||||||
|
node, err := h.manager.newNode(h.T, name, extraArgs, password, true)
|
||||||
|
require.NoErrorf(h, err, "unable to create new node for %s", name)
|
||||||
|
|
||||||
|
// Start the node with seed only, which will only create the `State`
|
||||||
|
// and `WalletUnlocker` clients.
|
||||||
|
err = node.StartWithSeed(h.runCtx)
|
||||||
|
require.NoErrorf(h, err, "failed to start node %s", node.Name())
|
||||||
|
|
||||||
|
// Create the wallet.
|
||||||
|
initReq := &lnrpc.InitWalletRequest{
|
||||||
|
WalletPassword: password,
|
||||||
|
CipherSeedMnemonic: mnemonic,
|
||||||
|
AezeedPassphrase: password,
|
||||||
|
ExtendedMasterKey: rootKey,
|
||||||
|
RecoveryWindow: recoveryWindow,
|
||||||
|
ChannelBackups: chanBackups,
|
||||||
|
}
|
||||||
|
_, err = h.manager.initWalletAndNode(node, initReq)
|
||||||
|
require.NoErrorf(h, err, "failed to unlock and init node %s",
|
||||||
|
node.Name())
|
||||||
|
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
|
||||||
// SetFeeEstimate sets a fee rate to be returned from fee estimator.
|
// SetFeeEstimate sets a fee rate to be returned from fee estimator.
|
||||||
//
|
//
|
||||||
// NOTE: this method will set the fee rate for a conf target of 1, which is the
|
// NOTE: this method will set the fee rate for a conf target of 1, which is the
|
||||||
|
@@ -194,3 +194,28 @@ func (nm *nodeManager) restartNodeNoUnlock(ctxt context.Context,
|
|||||||
|
|
||||||
return node.Start(ctxt)
|
return node.Start(ctxt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// initWalletAndNode will unlock the node's wallet and finish setting up the
|
||||||
|
// node so it's ready to take RPC requests.
|
||||||
|
func (nm *nodeManager) initWalletAndNode(hn *node.HarnessNode,
|
||||||
|
req *lnrpc.InitWalletRequest) ([]byte, error) {
|
||||||
|
|
||||||
|
// Pass the init request via rpc to finish unlocking the node.
|
||||||
|
resp := hn.RPC.InitWallet(req)
|
||||||
|
|
||||||
|
// Now that the wallet is unlocked, before creating an authed
|
||||||
|
// connection we will close the old unauthed connection.
|
||||||
|
if err := hn.CloseConn(); err != nil {
|
||||||
|
return nil, fmt.Errorf("close unauthed conn failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init the node, which will create the authed grpc conn and all its
|
||||||
|
// rpc clients.
|
||||||
|
err := hn.InitNode(resp.AdminMacaroon)
|
||||||
|
|
||||||
|
// In stateless initialization mode we get a macaroon back that we have
|
||||||
|
// to return to the test, otherwise gRPC calls won't be possible since
|
||||||
|
// there are no macaroon files created in that mode.
|
||||||
|
// In stateful init the admin macaroon will just be nil.
|
||||||
|
return resp.AdminMacaroon, err
|
||||||
|
}
|
||||||
|
@@ -23,3 +23,28 @@ func (h *HarnessRPC) UnlockWallet(
|
|||||||
|
|
||||||
return resp
|
return resp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// InitWallet makes a RPC request to WalletUnlocker and asserts there's no
|
||||||
|
// error.
|
||||||
|
func (h *HarnessRPC) InitWallet(
|
||||||
|
req *lnrpc.InitWalletRequest) *lnrpc.InitWalletResponse {
|
||||||
|
|
||||||
|
ctxt, cancel := context.WithTimeout(h.runCtx, DefaultTimeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
resp, err := h.WalletUnlocker.InitWallet(ctxt, req)
|
||||||
|
h.NoError(err, "InitWallet")
|
||||||
|
|
||||||
|
return resp
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenSeed makes a RPC request to WalletUnlocker and asserts there's no error.
|
||||||
|
func (h *HarnessRPC) GenSeed(req *lnrpc.GenSeedRequest) *lnrpc.GenSeedResponse {
|
||||||
|
ctxt, cancel := context.WithTimeout(h.runCtx, DefaultTimeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
resp, err := h.WalletUnlocker.GenSeed(ctxt, req)
|
||||||
|
h.NoError(err, "GenSeed")
|
||||||
|
|
||||||
|
return resp
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user