b7ba2697c8
The walletunlocker package contains the UnlockerService, which implements the lnrpc.WalletUnlocker interface. This service is used for receiving a password from the user over RPC, and doing simple validity checks like making sure the user is not trying to create a new wallet if one already exists, and that in case the wallet exists, the provided password is correct. The service will the pass the passwords over the CreatePasswords or UnlockPasswords channels, for use within lnd.go.
150 lines
3.9 KiB
Go
150 lines
3.9 KiB
Go
package walletunlocker_test
|
|
|
|
import (
|
|
"bytes"
|
|
"io/ioutil"
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/lightningnetwork/lnd/lnrpc"
|
|
"github.com/lightningnetwork/lnd/lnwallet/btcwallet"
|
|
"github.com/lightningnetwork/lnd/walletunlocker"
|
|
"github.com/roasbeef/btcd/chaincfg"
|
|
"github.com/roasbeef/btcwallet/wallet"
|
|
"golang.org/x/net/context"
|
|
)
|
|
|
|
const (
|
|
walletDbName = "wallet.db"
|
|
)
|
|
|
|
var (
|
|
testPassword = []byte("test-password")
|
|
testSeed = []byte("test-seed-123456789")
|
|
|
|
testNetParams = &chaincfg.MainNetParams
|
|
)
|
|
|
|
func createTestWallet(t *testing.T, dir string, netParams *chaincfg.Params) {
|
|
netDir := btcwallet.NetworkDir(dir, netParams)
|
|
loader := wallet.NewLoader(netParams, netDir)
|
|
_, err := loader.CreateNewWallet(testPassword, testPassword, testSeed)
|
|
if err != nil {
|
|
t.Fatalf("failed creating wallet: %v", err)
|
|
}
|
|
err = loader.UnloadWallet()
|
|
if err != nil {
|
|
t.Fatalf("failed unloading wallet: %v", err)
|
|
}
|
|
}
|
|
|
|
// TestCreateWallet checks that CreateWallet correctly returns a password that
|
|
// can be used for creating a wallet if no wallet exists from before, and
|
|
// returns an error when it already exists.
|
|
func TestCreateWallet(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
// testDir is empty, meaning wallet was not created from before.
|
|
testDir, err := ioutil.TempDir("", "testcreate")
|
|
if err != nil {
|
|
t.Fatalf("unable to create temp directory: %v", err)
|
|
}
|
|
defer func() {
|
|
os.RemoveAll(testDir)
|
|
}()
|
|
|
|
// Create new UnlockerService.
|
|
service := walletunlocker.New(nil, testDir, testNetParams)
|
|
|
|
ctx := context.Background()
|
|
req := &lnrpc.CreateWalletRequest{
|
|
Password: testPassword,
|
|
}
|
|
_, err = service.CreateWallet(ctx, req)
|
|
if err != nil {
|
|
t.Fatalf("CreateWallet call failed: %v", err)
|
|
}
|
|
|
|
// Password should be sent over the channel.
|
|
select {
|
|
case pw := <-service.CreatePasswords:
|
|
if !bytes.Equal(pw, testPassword) {
|
|
t.Fatalf("expected to receive password %x, got %x",
|
|
testPassword, pw)
|
|
}
|
|
case <-time.After(3 * time.Second):
|
|
t.Fatalf("password not received")
|
|
}
|
|
|
|
// Create a wallet in testDir.
|
|
createTestWallet(t, testDir, testNetParams)
|
|
|
|
// Now calling CreateWallet should fail, since a wallet already exists
|
|
// in the directory.
|
|
_, err = service.CreateWallet(ctx, req)
|
|
if err == nil {
|
|
t.Fatalf("CreateWallet did not fail as expected")
|
|
}
|
|
}
|
|
|
|
// TestUnlockWallet checks that trying to unlock non-existing wallet fail,
|
|
// that unlocking existing wallet with wrong passphrase fails, and that
|
|
// unlocking existing wallet with correct passphrase succeeds.
|
|
func TestUnlockWallet(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
// testDir is empty, meaning wallet was not created from before.
|
|
testDir, err := ioutil.TempDir("", "testunlock")
|
|
if err != nil {
|
|
t.Fatalf("unable to create temp directory: %v", err)
|
|
}
|
|
defer func() {
|
|
os.RemoveAll(testDir)
|
|
}()
|
|
|
|
// Create new UnlockerService.
|
|
service := walletunlocker.New(nil, testDir, testNetParams)
|
|
|
|
ctx := context.Background()
|
|
req := &lnrpc.UnlockWalletRequest{
|
|
Password: testPassword,
|
|
}
|
|
|
|
// Should fail to unlock non-existing wallet.
|
|
_, err = service.UnlockWallet(ctx, req)
|
|
if err == nil {
|
|
t.Fatalf("expected call to UnlockWallet to fail")
|
|
}
|
|
|
|
// Create a wallet we can try to unlock.
|
|
createTestWallet(t, testDir, testNetParams)
|
|
|
|
// Try unlocking this wallet with the wrong passphrase.
|
|
wrongReq := &lnrpc.UnlockWalletRequest{
|
|
Password: []byte("wrong-ofc"),
|
|
}
|
|
_, err = service.UnlockWallet(ctx, wrongReq)
|
|
if err == nil {
|
|
t.Fatalf("expected call to UnlockWallet to fail")
|
|
}
|
|
|
|
// With the correct password, we should be able to unlock the wallet.
|
|
_, err = service.UnlockWallet(ctx, req)
|
|
if err != nil {
|
|
t.Fatalf("unable to unlock wallet: %v", err)
|
|
}
|
|
|
|
// Password should be sent over the channel.
|
|
select {
|
|
case pw := <-service.UnlockPasswords:
|
|
if !bytes.Equal(pw, testPassword) {
|
|
t.Fatalf("expected to receive password %x, got %x",
|
|
testPassword, pw)
|
|
}
|
|
case <-time.After(3 * time.Second):
|
|
t.Fatalf("password not received")
|
|
}
|
|
|
|
}
|