github.com/decred/dcrlnd@v0.7.6/lnwallet/remotedcrwallet/keychain_test.go (about)

     1  package remotedcrwallet
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"os"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/decred/dcrlnd/channeldb"
    12  	"github.com/decred/dcrlnd/keychain"
    13  	"github.com/decred/dcrlnd/lnwallet"
    14  
    15  	base "decred.org/dcrwallet/v4/wallet"
    16  
    17  	"github.com/decred/dcrd/chaincfg/chainhash"
    18  	"github.com/decred/dcrd/chaincfg/v3"
    19  	"github.com/decred/dcrd/hdkeychain/v3"
    20  	"github.com/decred/dcrd/txscript/v4/stdaddr"
    21  	walletloader "github.com/decred/dcrlnd/lnwallet/dcrwallet/loader"
    22  )
    23  
    24  var (
    25  	testHDSeed = chainhash.Hash{
    26  		0xb7, 0x94, 0x38, 0x5f, 0x2d, 0x1e, 0xf7, 0xab,
    27  		0x4d, 0x92, 0x73, 0xd1, 0x90, 0x63, 0x81, 0xb4,
    28  		0x4f, 0x2f, 0x6f, 0x25, 0x98, 0xa3, 0xef, 0xb9,
    29  		0x69, 0x49, 0x18, 0x83, 0x31, 0x98, 0x47, 0x53,
    30  	}
    31  )
    32  
    33  type mockOnchainAddrSourcer struct {
    34  	w *base.Wallet
    35  }
    36  
    37  func (mas *mockOnchainAddrSourcer) NewAddress(t lnwallet.AddressType, change bool,
    38  	accountName string) (stdaddr.Address, error) {
    39  	var addr stdaddr.Address
    40  	var err error
    41  	if change {
    42  		addr, err = mas.w.NewInternalAddress(context.TODO(), 0)
    43  	} else {
    44  		addr, err = mas.w.NewExternalAddress(context.TODO(), 0)
    45  	}
    46  
    47  	if err != nil {
    48  		return nil, err
    49  	}
    50  
    51  	// Convert to a regular p2pkh address, since the addresses returned are
    52  	// used as paramaters to PayT.(stdaddr.Hash160er).Hash160()[:] which doesn't understand
    53  	// the native wallet types.
    54  	return stdaddr.DecodeAddress(addr.String(), chaincfg.SimNetParams())
    55  
    56  }
    57  func (mas *mockOnchainAddrSourcer) Bip44AddressInfo(addr stdaddr.Address) (uint32, uint32, uint32, error) {
    58  	info, err := mas.w.KnownAddress(context.Background(), addr)
    59  	if err != nil {
    60  		return 0, 0, 0, nil
    61  	}
    62  
    63  	switch ma := info.(type) {
    64  	case base.BIP0044Address:
    65  		acct, branch, child := ma.Path()
    66  		return acct, branch, child, nil
    67  	}
    68  
    69  	return 0, 0, 0, fmt.Errorf("unkown address type")
    70  }
    71  
    72  func createTestWallet() (func(), *hdkeychain.ExtendedKey, *channeldb.DB, onchainAddrSourcer, error) {
    73  	tempDir, err := ioutil.TempDir("", "keyring-lnwallet")
    74  	if err != nil {
    75  		return nil, nil, nil, nil, err
    76  	}
    77  	loader := walletloader.NewLoader(chaincfg.SimNetParams(), tempDir, 20)
    78  
    79  	pass := []byte("test")
    80  
    81  	birthday := time.Now().Add(-time.Hour * 24)
    82  	baseWallet, err := loader.CreateNewWallet(
    83  		context.Background(), pass, pass, testHDSeed[:], birthday,
    84  	)
    85  	if err != nil {
    86  		return nil, nil, nil, nil, err
    87  	}
    88  
    89  	if err := baseWallet.Unlock(context.Background(), pass, nil); err != nil {
    90  		return nil, nil, nil, nil, err
    91  	}
    92  
    93  	// Create the temp chandb dir.
    94  	cdbDir, err := ioutil.TempDir("", "channeldb")
    95  	if err != nil {
    96  		return nil, nil, nil, nil, err
    97  	}
    98  
    99  	// Next, create channeldb for the first time.
   100  	cdb, err := channeldb.Open(cdbDir)
   101  	if err != nil {
   102  		return nil, nil, nil, nil, err
   103  	}
   104  
   105  	// The root master xpriv is the default account's one.
   106  	acctXpriv, err := baseWallet.AccountXpriv(context.Background(), 0)
   107  	if err != nil {
   108  		return nil, nil, nil, nil, err
   109  	}
   110  
   111  	// Create the mock onchain addresses sourcer linked to the previously
   112  	// created wallet.
   113  	addrSourcer := &mockOnchainAddrSourcer{w: baseWallet}
   114  
   115  	cleanUp := func() {
   116  		baseWallet.Lock()
   117  		os.RemoveAll(tempDir)
   118  		cdb.Close()
   119  		os.RemoveAll(cdbDir)
   120  	}
   121  
   122  	return cleanUp, acctXpriv, cdb, addrSourcer, nil
   123  }
   124  
   125  // TestDcrwalletKeyRingImpl tests whether the walletKeyRing implementation
   126  // conforms to the required interface spec.
   127  func TestDcrwalletKeyRingImpl(t *testing.T) {
   128  	t.Parallel()
   129  
   130  	keychain.CheckKeyRingImpl(t,
   131  		func() (string, func(), keychain.KeyRing, error) {
   132  			cleanUp, rootXPriv, cdb, addrSourcer, err := createTestWallet()
   133  			if err != nil {
   134  				t.Fatalf("unable to create wallet: %v", err)
   135  			}
   136  
   137  			keyRing, err := newRemoteWalletKeyRing(
   138  				rootXPriv, cdb, addrSourcer,
   139  			)
   140  
   141  			return "dcrwallet", cleanUp, keyRing, err
   142  		},
   143  	)
   144  
   145  }
   146  
   147  // TestDcrwalletSecretKeyRingImpl tests whether the walletKeyRing
   148  // implementation conforms to the required interface spec.
   149  func TestDcrwalletSecretKeyRingImpl(t *testing.T) {
   150  	t.Parallel()
   151  
   152  	keychain.CheckSecretKeyRingImpl(t,
   153  		func() (string, func(), keychain.SecretKeyRing, error) {
   154  			cleanUp, rootXPriv, cdb, addrSourcer, err := createTestWallet()
   155  			if err != nil {
   156  				t.Fatalf("unable to create wallet: %v", err)
   157  			}
   158  
   159  			keyRing, err := newRemoteWalletKeyRing(
   160  				rootXPriv, cdb, addrSourcer,
   161  			)
   162  
   163  			return "dcrwallet", cleanUp, keyRing, err
   164  		},
   165  	)
   166  
   167  }
   168  
   169  func init() {
   170  	// We'll clamp the max range scan to constrain the run time of the
   171  	// private key scan test.
   172  	keychain.MaxKeyRangeScan = 3
   173  }