keystore_test.go raw

   1  package keystore
   2  
   3  import (
   4  	"bytes"
   5  	"crypto/rand"
   6  	"github.com/p9c/p9/pkg/btcaddr"
   7  	"github.com/p9c/p9/pkg/chaincfg"
   8  	"math/big"
   9  	"reflect"
  10  	"testing"
  11  	
  12  	"github.com/davecgh/go-spew/spew"
  13  	
  14  	"github.com/p9c/p9/pkg/chainhash"
  15  	ec "github.com/p9c/p9/pkg/ecc"
  16  	"github.com/p9c/p9/pkg/txscript"
  17  	"github.com/p9c/p9/pkg/util"
  18  )
  19  
  20  const dummyDir = ""
  21  
  22  var tstNetParams = &chaincfg.MainNetParams
  23  
  24  func makeBS(height int32) *BlockStamp {
  25  	return &BlockStamp{
  26  		Hash:   new(chainhash.Hash),
  27  		Height: height,
  28  	}
  29  }
  30  func TestBtcAddressSerializer(t *testing.T) {
  31  	fakeWallet := &Store{net: (*netParams)(tstNetParams)}
  32  	kdfp := &kdfParameters{
  33  		mem:   1024,
  34  		nIter: 5,
  35  	}
  36  	var e error
  37  	if _, e = rand.Read(kdfp.salt[:]); E.Chk(e) {
  38  		t.Error(e.Error())
  39  		return
  40  	}
  41  	key := kdf([]byte("banana"), kdfp)
  42  	privKey := make([]byte, 32)
  43  	if _, e = rand.Read(privKey); E.Chk(e) {
  44  		t.Error(e.Error())
  45  		return
  46  	}
  47  	addr, e := newBtcAddress(fakeWallet, privKey, nil,
  48  		makeBS(0), true,
  49  	)
  50  	if e != nil {
  51  		t.Error(e.Error())
  52  		return
  53  	}
  54  	e = addr.encrypt(key)
  55  	if e != nil {
  56  		t.Error(e.Error())
  57  		return
  58  	}
  59  	buf := new(bytes.Buffer)
  60  	if _, e = addr.WriteTo(buf); E.Chk(e) {
  61  		t.Error(e.Error())
  62  		return
  63  	}
  64  	var readAddr btcAddress
  65  	readAddr.store = fakeWallet
  66  	_, e = readAddr.ReadFrom(buf)
  67  	if e != nil {
  68  		t.Error(e.Error())
  69  		return
  70  	}
  71  	if _, e = readAddr.unlock(key); E.Chk(e) {
  72  		t.Error(e.Error())
  73  		return
  74  	}
  75  	if !reflect.DeepEqual(addr, &readAddr) {
  76  		t.Error("Original and read btcAddress differ.")
  77  	}
  78  }
  79  func TestScriptAddressSerializer(t *testing.T) {
  80  	fakeWallet := &Store{net: (*netParams)(tstNetParams)}
  81  	script := []byte{txscript.OP_TRUE, txscript.OP_DUP,
  82  		txscript.OP_DROP,
  83  	}
  84  	addr, e := newScriptAddress(fakeWallet, script, makeBS(0))
  85  	if e != nil {
  86  		t.Error(e.Error())
  87  		return
  88  	}
  89  	buf := new(bytes.Buffer)
  90  	if _, e = addr.WriteTo(buf); E.Chk(e) {
  91  		t.Error(e.Error())
  92  		return
  93  	}
  94  	var readAddr scriptAddress
  95  	readAddr.store = fakeWallet
  96  	_, e = readAddr.ReadFrom(buf)
  97  	if e != nil {
  98  		t.Error(e.Error())
  99  		return
 100  	}
 101  	if !reflect.DeepEqual(addr, &readAddr) {
 102  		t.Error("Original and read btcAddress differ.")
 103  	}
 104  }
 105  func TestWalletCreationSerialization(t *testing.T) {
 106  	createdAt := makeBS(0)
 107  	w1, e := New(dummyDir, "A wallet for testing.",
 108  		[]byte("banana"), tstNetParams, createdAt,
 109  	)
 110  	if e != nil {
 111  		t.Error("ScriptError creating new wallet: " + e.Error())
 112  		return
 113  	}
 114  	buf := new(bytes.Buffer)
 115  	if _, e = w1.WriteTo(buf); E.Chk(e) {
 116  		t.Error("ScriptError writing new wallet: " + e.Error())
 117  		return
 118  	}
 119  	w2 := new(Store)
 120  	_, e = w2.ReadFrom(buf)
 121  	if e != nil {
 122  		t.Error("ScriptError reading newly written wallet: " + e.Error())
 123  		return
 124  	}
 125  	e = w1.Lock()
 126  	if e != nil {
 127  		t.Log(e)
 128  	}
 129  	e = w2.Lock()
 130  	if e != nil {
 131  		t.Log(e)
 132  	}
 133  	if e = w1.Unlock([]byte("banana")); E.Chk(e) {
 134  		t.Error("Decrypting original wallet failed: " + e.Error())
 135  		return
 136  	}
 137  	if e = w2.Unlock([]byte("banana")); E.Chk(e) {
 138  		t.Error("Decrypting newly read wallet failed: " + e.Error())
 139  		return
 140  	}
 141  	//	if !reflect.DeepEqual(w1, w2) {
 142  	//		t.ScriptError("Created and read-in wallets do not match.")
 143  	//		spew.Dump(w1, w2)
 144  	//		return
 145  	//	}
 146  }
 147  func TestChaining(t *testing.T) {
 148  	tests := []struct {
 149  		name                       string
 150  		cc                         []byte
 151  		origPrivateKey             []byte
 152  		nextPrivateKeyUncompressed []byte
 153  		nextPrivateKeyCompressed   []byte
 154  		nextPublicKeyUncompressed  []byte
 155  		nextPublicKeyCompressed    []byte
 156  	}{
 157  		{
 158  			name:           "chaintest 1",
 159  			cc:             []byte("3318959fff419ab8b556facb3c429a86"),
 160  			origPrivateKey: []byte("5ffc975976eaaa1f7b179f384ebbc053"),
 161  			nextPrivateKeyUncompressed: []byte{
 162  				0xd3, 0xfe, 0x2e, 0x96, 0x44, 0x12, 0x2d, 0xaa,
 163  				0x80, 0x8e, 0x36, 0x17, 0xb5, 0x9f, 0x8c, 0xd2,
 164  				0x72, 0x8c, 0xaf, 0xf1, 0xdb, 0xd6, 0x4a, 0x92,
 165  				0xd7, 0xc7, 0xee, 0x2b, 0x56, 0x34, 0xe2, 0x87,
 166  			},
 167  			nextPrivateKeyCompressed: []byte{
 168  				0x08, 0x56, 0x7a, 0x1b, 0x89, 0x56, 0x2e, 0xfa,
 169  				0xb4, 0x02, 0x59, 0x69, 0x10, 0xc3, 0x60, 0x1f,
 170  				0x34, 0xf0, 0x55, 0x02, 0x8a, 0xbf, 0x37, 0xf5,
 171  				0x22, 0x80, 0x9f, 0xd2, 0xe5, 0x42, 0x5b, 0x2d,
 172  			},
 173  			nextPublicKeyUncompressed: []byte{
 174  				0x04, 0xdd, 0x70, 0x31, 0xa5, 0xf9, 0x06, 0x70,
 175  				0xd3, 0x9a, 0x24, 0x5b, 0xd5, 0x73, 0xdd, 0xb6,
 176  				0x15, 0x81, 0x0b, 0x78, 0x19, 0xbc, 0xc8, 0x26,
 177  				0xc9, 0x16, 0x86, 0x73, 0xae, 0xe4, 0xc0, 0xed,
 178  				0x39, 0x81, 0xb4, 0x86, 0x2d, 0x19, 0x8c, 0x67,
 179  				0x9c, 0x93, 0x99, 0xf6, 0xd2, 0x3f, 0xd1, 0x53,
 180  				0x9e, 0xed, 0xbd, 0x07, 0xd6, 0x4f, 0xa9, 0x81,
 181  				0x61, 0x85, 0x46, 0x84, 0xb1, 0xa0, 0xed, 0xbc,
 182  				0xa7,
 183  			},
 184  			nextPublicKeyCompressed: []byte{
 185  				0x02, 0x2c, 0x48, 0x73, 0x37, 0x35, 0x74, 0x7f,
 186  				0x05, 0x58, 0xc1, 0x4e, 0x0d, 0x18, 0xc2, 0xbf,
 187  				0xcc, 0x83, 0xa2, 0x4d, 0x64, 0xab, 0xba, 0xea,
 188  				0xeb, 0x4c, 0xcd, 0x4c, 0x0c, 0x21, 0xc4, 0x30,
 189  				0x0f,
 190  			},
 191  		},
 192  	}
 193  	for _, test := range tests {
 194  		// Create both uncompressed and compressed public keys for original
 195  		// private key.
 196  		origPubUncompressed := pubkeyFromPrivkey(test.origPrivateKey, false)
 197  		origPubCompressed := pubkeyFromPrivkey(test.origPrivateKey, true)
 198  		// Create next chained private keys, chained from both the uncompressed
 199  		// and compressed pubkeys.
 200  		nextPrivUncompressed, e := chainedPrivKey(test.origPrivateKey,
 201  			origPubUncompressed, test.cc,
 202  		)
 203  		if e != nil {
 204  			t.Errorf("%s: Uncompressed chainedPrivKey failed: %v", test.name, e)
 205  			return
 206  		}
 207  		nextPrivCompressed, e := chainedPrivKey(test.origPrivateKey,
 208  			origPubCompressed, test.cc,
 209  		)
 210  		if e != nil {
 211  			t.Errorf("%s: Compressed chainedPrivKey failed: %v", test.name, e)
 212  			return
 213  		}
 214  		// Verify that the new private keys match the expected values
 215  		// in the test case.
 216  		if !bytes.Equal(nextPrivUncompressed, test.nextPrivateKeyUncompressed) {
 217  			t.Errorf("%s: Next private key (from uncompressed pubkey) does not match expected.\nGot: %s\nExpected: %s",
 218  				test.name, spew.Sdump(nextPrivUncompressed), spew.Sdump(test.nextPrivateKeyUncompressed),
 219  			)
 220  			return
 221  		}
 222  		if !bytes.Equal(nextPrivCompressed, test.nextPrivateKeyCompressed) {
 223  			t.Errorf("%s: Next private key (from compressed pubkey) does not match expected.\nGot: %s\nExpected: %s",
 224  				test.name, spew.Sdump(nextPrivCompressed), spew.Sdump(test.nextPrivateKeyCompressed),
 225  			)
 226  			return
 227  		}
 228  		// Create the next pubkeys generated from the next private keys.
 229  		nextPubUncompressedFromPriv := pubkeyFromPrivkey(nextPrivUncompressed, false)
 230  		nextPubCompressedFromPriv := pubkeyFromPrivkey(nextPrivCompressed, true)
 231  		// Create the next pubkeys by chaining directly off the original
 232  		// pubkeys (without using the original's private key).
 233  		nextPubUncompressedFromPub, e := chainedPubKey(origPubUncompressed, test.cc)
 234  		if e != nil {
 235  			t.Errorf("%s: Uncompressed chainedPubKey failed: %v", test.name, e)
 236  			return
 237  		}
 238  		nextPubCompressedFromPub, e := chainedPubKey(origPubCompressed, test.cc)
 239  		if e != nil {
 240  			t.Errorf("%s: Compressed chainedPubKey failed: %v", test.name, e)
 241  			return
 242  		}
 243  		// Public keys (used to generate the bitcoin address) MUST match.
 244  		if !bytes.Equal(nextPubUncompressedFromPriv, nextPubUncompressedFromPub) {
 245  			t.Errorf("%s: Uncompressed public keys do not match.", test.name)
 246  		}
 247  		if !bytes.Equal(nextPubCompressedFromPriv, nextPubCompressedFromPub) {
 248  			t.Errorf("%s: Compressed public keys do not match.", test.name)
 249  		}
 250  		// Verify that all generated public keys match the expected
 251  		// values in the test case.
 252  		if !bytes.Equal(nextPubUncompressedFromPub, test.nextPublicKeyUncompressed) {
 253  			t.Errorf("%s: Next uncompressed public keys do not match expected value.\nGot: %s\nExpected: %s",
 254  				test.name, spew.Sdump(nextPubUncompressedFromPub), spew.Sdump(test.nextPublicKeyUncompressed),
 255  			)
 256  			return
 257  		}
 258  		if !bytes.Equal(nextPubCompressedFromPub, test.nextPublicKeyCompressed) {
 259  			t.Errorf("%s: Next compressed public keys do not match expected value.\nGot: %s\nExpected: %s",
 260  				test.name, spew.Sdump(nextPubCompressedFromPub), spew.Sdump(test.nextPublicKeyCompressed),
 261  			)
 262  			return
 263  		}
 264  		// Sign data with the next private keys and verify signature with
 265  		// the next pubkeys.
 266  		pubkeyUncompressed, e := ec.ParsePubKey(nextPubUncompressedFromPub, ec.S256())
 267  		if e != nil {
 268  			t.Errorf("%s: Unable to parse next uncompressed pubkey: %v", test.name, e)
 269  			return
 270  		}
 271  		pubkeyCompressed, e := ec.ParsePubKey(nextPubCompressedFromPub, ec.S256())
 272  		if e != nil {
 273  			t.Errorf("%s: Unable to parse next compressed pubkey: %v", test.name, e)
 274  			return
 275  		}
 276  		privkeyUncompressed := &ec.PrivateKey{
 277  			PublicKey: *pubkeyUncompressed.ToECDSA(),
 278  			D:         new(big.Int).SetBytes(nextPrivUncompressed),
 279  		}
 280  		privkeyCompressed := &ec.PrivateKey{
 281  			PublicKey: *pubkeyCompressed.ToECDSA(),
 282  			D:         new(big.Int).SetBytes(nextPrivCompressed),
 283  		}
 284  		data := "String to sign."
 285  		sig, e := privkeyUncompressed.Sign([]byte(data))
 286  		if e != nil {
 287  			t.Errorf("%s: Unable to sign data with next private key (chained from uncompressed pubkey): %v",
 288  				test.name, e,
 289  			)
 290  			return
 291  		}
 292  		ok := sig.Verify([]byte(data), privkeyUncompressed.PubKey())
 293  		if !ok {
 294  			t.Errorf("%s: ec signature verification failed for next keypair (chained from uncompressed pubkey).",
 295  				test.name,
 296  			)
 297  			return
 298  		}
 299  		sig, e = privkeyCompressed.Sign([]byte(data))
 300  		if e != nil {
 301  			t.Errorf("%s: Unable to sign data with next private key (chained from compressed pubkey): %v",
 302  				test.name, e,
 303  			)
 304  			return
 305  		}
 306  		ok = sig.Verify([]byte(data), privkeyCompressed.PubKey())
 307  		if !ok {
 308  			t.Errorf("%s: ec signature verification failed for next keypair (chained from compressed pubkey).",
 309  				test.name,
 310  			)
 311  			return
 312  		}
 313  	}
 314  }
 315  func TestWalletPubkeyChaining(t *testing.T) {
 316  	w, e := New(dummyDir, "A wallet for testing.",
 317  		[]byte("banana"), tstNetParams, makeBS(0),
 318  	)
 319  	if e != nil {
 320  		t.Error("ScriptError creating new wallet: " + e.Error())
 321  		return
 322  	}
 323  	if !w.IsLocked() {
 324  		t.Error("New wallet is not locked.")
 325  	}
 326  	// Get next chained address.  The wallet is locked, so this will chain
 327  	// off the last pubkey, not privkey.
 328  	addrWithoutPrivkey, e := w.NextChainedAddress(makeBS(0))
 329  	if e != nil {
 330  		t.Errorf("Failed to extend address chain from pubkey: %v", e)
 331  		return
 332  	}
 333  	// Lookup address info.  This should succeed even without the private
 334  	// key available.
 335  	info, e := w.Address(addrWithoutPrivkey)
 336  	if e != nil {
 337  		t.Errorf("Failed to get info about address without private key: %v", e)
 338  		return
 339  	}
 340  	pkinfo := info.(PubKeyAddress)
 341  	// sanity checks
 342  	if !info.Compressed() {
 343  		t.Errorf("Pubkey should be compressed.")
 344  		return
 345  	}
 346  	if info.Imported() {
 347  		t.Errorf("Should not be marked as imported.")
 348  		return
 349  	}
 350  	pka := info.(PubKeyAddress)
 351  	// Try to lookup it's private key.  This should fail.
 352  	_, e = pka.PrivKey()
 353  	if e == nil {
 354  		t.Errorf("Incorrectly returned nil error for looking up private key for address without one saved.")
 355  		return
 356  	}
 357  	// Deserialize w and serialize into a new wallet.  The rest of the checks
 358  	// in this test test against both a fresh, as well as an "opened and closed"
 359  	// wallet with the missing private key.
 360  	serializedWallet := new(bytes.Buffer)
 361  	_, e = w.WriteTo(serializedWallet)
 362  	if e != nil {
 363  		t.Errorf("ScriptError writing wallet with missing private key: %v", e)
 364  		return
 365  	}
 366  	w2 := new(Store)
 367  	_, e = w2.ReadFrom(serializedWallet)
 368  	if e != nil {
 369  		t.Errorf("ScriptError reading wallet with missing private key: %v", e)
 370  		return
 371  	}
 372  	// Unlock wallet.  This should trigger creating the private key for
 373  	// the address.
 374  	if e = w.Unlock([]byte("banana")); E.Chk(e) {
 375  		t.Errorf("Can't unlock original wallet: %v", e)
 376  		return
 377  	}
 378  	if e = w2.Unlock([]byte("banana")); E.Chk(e) {
 379  		t.Errorf("Can't unlock re-read wallet: %v", e)
 380  		return
 381  	}
 382  	// Same address, better variable name.
 383  	addrWithPrivKey := addrWithoutPrivkey
 384  	// Try a private key lookup again.  The private key should now be available.
 385  	key1, e := pka.PrivKey()
 386  	if e != nil {
 387  		t.Errorf("Private key for original wallet was not created! %v", e)
 388  		return
 389  	}
 390  	info2, e := w.Address(addrWithPrivKey)
 391  	if e != nil {
 392  		t.Errorf("no address in re-read wallet")
 393  	}
 394  	pka2 := info2.(PubKeyAddress)
 395  	key2, e := pka2.PrivKey()
 396  	if e != nil {
 397  		t.Errorf("Private key for re-read wallet was not created! %v", e)
 398  		return
 399  	}
 400  	// Keys returned by both wallets must match.
 401  	if !reflect.DeepEqual(key1, key2) {
 402  		t.Errorf("Private keys for address originally created without one mismtach between original and re-read wallet.")
 403  		return
 404  	}
 405  	// Sign some data with the private key, then verify signature with the pubkey.
 406  	hash := []byte("hash to sign")
 407  	sig, e := key1.Sign(hash)
 408  	if e != nil {
 409  		t.Errorf("Unable to sign hash with the created private key: %v", e)
 410  		return
 411  	}
 412  	pubKey := pkinfo.PubKey()
 413  	ok := sig.Verify(hash, pubKey)
 414  	if !ok {
 415  		t.Errorf("ec signature verification failed; address's pubkey mismatches the privkey.")
 416  		return
 417  	}
 418  	nextAddr, e := w.NextChainedAddress(makeBS(0))
 419  	if e != nil {
 420  		t.Errorf("Unable to create next address after finding the privkey: %v", e)
 421  		return
 422  	}
 423  	nextInfo, e := w.Address(nextAddr)
 424  	if e != nil {
 425  		t.Errorf("Couldn't get info about the next address in the chain: %v", e)
 426  		return
 427  	}
 428  	nextPkInfo := nextInfo.(PubKeyAddress)
 429  	nextKey, e := nextPkInfo.PrivKey()
 430  	if e != nil {
 431  		t.Errorf("Couldn't get private key for the next address in the chain: %v", e)
 432  		return
 433  	}
 434  	// Do a signature check here as well, this time for the next
 435  	// address after the one made without the private key.
 436  	sig, e = nextKey.Sign(hash)
 437  	if e != nil {
 438  		t.Errorf("Unable to sign hash with the created private key: %v", e)
 439  		return
 440  	}
 441  	pubKey = nextPkInfo.PubKey()
 442  	ok = sig.Verify(hash, pubKey)
 443  	if !ok {
 444  		t.Errorf("ec signature verification failed; next address's keypair does not match.")
 445  		return
 446  	}
 447  	// Chk that the serialized wallet correctly unmarked the 'needs private
 448  	// keys later' flag.
 449  	buf := new(bytes.Buffer)
 450  	_, e = w2.WriteTo(buf)
 451  	if e != nil {
 452  		t.Log(e)
 453  	}
 454  	_, e = w2.ReadFrom(buf)
 455  	if e != nil {
 456  		t.Log(e)
 457  	}
 458  	e = w2.Unlock([]byte("banana"))
 459  	if e != nil {
 460  		t.Errorf("Unlock after serialize/deserialize failed: %v", e)
 461  		return
 462  	}
 463  }
 464  func TestWatchingWalletExport(t *testing.T) {
 465  	createdAt := makeBS(0)
 466  	w, e := New(dummyDir, "A wallet for testing.",
 467  		[]byte("banana"), tstNetParams, createdAt,
 468  	)
 469  	if e != nil {
 470  		t.Error("ScriptError creating new wallet: " + e.Error())
 471  		return
 472  	}
 473  	// Maintain a set of the active addresses in the wallet.
 474  	activeAddrs := make(map[addressKey]struct{})
 475  	// Add root address.
 476  	activeAddrs[getAddressKey(w.LastChainedAddress())] = struct{}{}
 477  	// Create watching wallet from w.
 478  	ww, e := w.ExportWatchingWallet()
 479  	if e != nil {
 480  		t.Errorf("Could not create watching wallet: %v", e)
 481  		return
 482  	}
 483  	// Verify correctness of wallet flags.
 484  	if ww.flags.useEncryption {
 485  		t.Errorf("Watching wallet marked as using encryption (but nothing to encrypt).")
 486  		return
 487  	}
 488  	if !ww.flags.watchingOnly {
 489  		t.Errorf("Wallet should be watching-only but is not marked so.")
 490  		return
 491  	}
 492  	// Verify that all flags are set as expected.
 493  	if ww.keyGenerator.flags.encrypted {
 494  		t.Errorf("Watching root address should not be encrypted (nothing to encrypt)")
 495  		return
 496  	}
 497  	if ww.keyGenerator.flags.hasPrivKey {
 498  		t.Errorf("Watching root address marked as having a private key.")
 499  		return
 500  	}
 501  	if !ww.keyGenerator.flags.hasPubKey {
 502  		t.Errorf("Watching root address marked as missing a public key.")
 503  		return
 504  	}
 505  	if ww.keyGenerator.flags.createPrivKeyNextUnlock {
 506  		t.Errorf("Watching root address marked as needing a private key to be generated later.")
 507  		return
 508  	}
 509  	for apkh, waddr := range ww.addrMap {
 510  		switch addr := waddr.(type) {
 511  		case *btcAddress:
 512  			if addr.flags.encrypted {
 513  				t.Errorf("Chained address should not be encrypted (nothing to encrypt)")
 514  				return
 515  			}
 516  			if addr.flags.hasPrivKey {
 517  				t.Errorf("Chained address marked as having a private key.")
 518  				return
 519  			}
 520  			if !addr.flags.hasPubKey {
 521  				t.Errorf("Chained address marked as missing a public key.")
 522  				return
 523  			}
 524  			if addr.flags.createPrivKeyNextUnlock {
 525  				t.Errorf("Chained address marked as needing a private key to be generated later.")
 526  				return
 527  			}
 528  		case *scriptAddress:
 529  			t.Errorf("Chained address was a script!")
 530  			return
 531  		default:
 532  			t.Errorf("Chained address unknown type!")
 533  			return
 534  		}
 535  		if _, ok := activeAddrs[apkh]; !ok {
 536  			t.Errorf("Address from watching wallet not found in original wallet.")
 537  			return
 538  		}
 539  		delete(activeAddrs, apkh)
 540  	}
 541  	if len(activeAddrs) != 0 {
 542  		t.Errorf("%v address(es) were not exported to watching wallet.", len(activeAddrs))
 543  		return
 544  	}
 545  	// Chk that the new addresses created by each wallet match.  The
 546  	// original wallet is unlocked so addresses are chained with privkeys.
 547  	if e = w.Unlock([]byte("banana")); E.Chk(e) {
 548  		t.Errorf("Unlocking original wallet failed: %v", e)
 549  	}
 550  	// Test that ExtendActiveAddresses for the watching wallet match
 551  	// manually requested addresses of the original wallet.
 552  	var newAddrs []btcaddr.Address
 553  	for i := 0; i < 10; i++ {
 554  		var addr btcaddr.Address
 555  		addr, e = w.NextChainedAddress(createdAt)
 556  		if e != nil {
 557  			t.Errorf("Cannot get next chained address for original wallet: %v", e)
 558  			return
 559  		}
 560  		newAddrs = append(newAddrs, addr)
 561  	}
 562  	newWWAddrs, e := ww.ExtendActiveAddresses(10)
 563  	if e != nil {
 564  		t.Errorf("Cannot extend active addresses for watching wallet: %v", e)
 565  		return
 566  	}
 567  	for i := range newAddrs {
 568  		if newAddrs[i].EncodeAddress() != newWWAddrs[i].EncodeAddress() {
 569  			t.Errorf("Extended active addresses do not match manually requested addresses.")
 570  			return
 571  		}
 572  	}
 573  	// Test ExtendActiveAddresses for the original wallet after manually
 574  	// requesting addresses for the watching wallet.
 575  	newWWAddrs = newWWAddrs[:0]
 576  	for i := 0; i < 10; i++ {
 577  		var addr btcaddr.Address
 578  		addr, e = ww.NextChainedAddress(createdAt)
 579  		if e != nil {
 580  			t.Errorf("Cannot get next chained address for watching wallet: %v", e)
 581  			return
 582  		}
 583  		newWWAddrs = append(newWWAddrs, addr)
 584  	}
 585  	newAddrs, e = w.ExtendActiveAddresses(10)
 586  	if e != nil {
 587  		t.Errorf("Cannot extend active addresses for original wallet: %v", e)
 588  		return
 589  	}
 590  	for i := range newAddrs {
 591  		if newAddrs[i].EncodeAddress() != newWWAddrs[i].EncodeAddress() {
 592  			t.Errorf("Extended active addresses do not match manually requested addresses.")
 593  			return
 594  		}
 595  	}
 596  	// Test (de)serialization of watching wallet.
 597  	buf := new(bytes.Buffer)
 598  	_, e = ww.WriteTo(buf)
 599  	if e != nil {
 600  		t.Errorf("Cannot write watching wallet: %v", e)
 601  		return
 602  	}
 603  	ww2 := new(Store)
 604  	_, e = ww2.ReadFrom(buf)
 605  	if e != nil {
 606  		t.Errorf("Cannot read watching wallet: %v", e)
 607  		return
 608  	}
 609  	// Chk that (de)serialized watching wallet matches the exported wallet.
 610  	if !reflect.DeepEqual(ww, ww2) {
 611  		t.Error("Exported and read-in watching wallets do not match.")
 612  		return
 613  	}
 614  	// Verify that nonsensical functions fail with correct error.
 615  	if e = ww.Lock(); e != ErrWatchingOnly {
 616  		t.Errorf("Nonsensical func Lock returned no or incorrect error: %v", e)
 617  		return
 618  	}
 619  	if e = ww.Unlock([]byte("banana")); e != ErrWatchingOnly {
 620  		t.Errorf("Nonsensical func Unlock returned no or incorrect error: %v", e)
 621  		return
 622  	}
 623  	generator, e := ww.Address(w.keyGenerator.Address())
 624  	if e != nil {
 625  		t.Errorf("generator isnt' present in wallet")
 626  	}
 627  	gpk := generator.(PubKeyAddress)
 628  	if _, e = gpk.PrivKey(); e != ErrWatchingOnly {
 629  		t.Errorf("Nonsensical func AddressKey returned no or incorrect error: %v", e)
 630  		return
 631  	}
 632  	if _, e = ww.ExportWatchingWallet(); e != ErrWatchingOnly {
 633  		t.Errorf("Nonsensical func ExportWatchingWallet returned no or incorrect error: %v", e)
 634  		return
 635  	}
 636  	pk, _ := ec.PrivKeyFromBytes(ec.S256(), make([]byte, 32))
 637  	wif, e := util.NewWIF(pk, tstNetParams, true)
 638  	if e != nil {
 639  		t.Fatal(e)
 640  	}
 641  	if _, e = ww.ImportPrivateKey(wif, createdAt); e != ErrWatchingOnly {
 642  		t.Errorf("Nonsensical func ImportPrivateKey returned no or incorrect error: %v", e)
 643  		return
 644  	}
 645  }
 646  func TestImportPrivateKey(t *testing.T) {
 647  	createHeight := int32(100)
 648  	createdAt := makeBS(createHeight)
 649  	w, e := New(dummyDir, "A wallet for testing.",
 650  		[]byte("banana"), tstNetParams, createdAt,
 651  	)
 652  	if e != nil {
 653  		t.Error("ScriptError creating new wallet: " + e.Error())
 654  		return
 655  	}
 656  	if e = w.Unlock([]byte("banana")); E.Chk(e) {
 657  		t.Errorf("Can't unlock original wallet: %v", e)
 658  		return
 659  	}
 660  	pk, e := ec.NewPrivateKey(ec.S256())
 661  	if e != nil {
 662  		t.Error("ScriptError generating private key: " + e.Error())
 663  		return
 664  	}
 665  	// verify that the entire wallet's sync height matches the
 666  	// expected createHeight.
 667  	if _, h := w.SyncedTo(); h != createHeight {
 668  		t.Errorf("Initial sync height %v does not match expected %v.", h, createHeight)
 669  		return
 670  	}
 671  	// import priv key
 672  	wif, e := util.NewWIF(pk, tstNetParams, false)
 673  	if e != nil {
 674  		t.Fatal(e)
 675  	}
 676  	importHeight := int32(50)
 677  	importedAt := makeBS(importHeight)
 678  	address, e := w.ImportPrivateKey(wif, importedAt)
 679  	if e != nil {
 680  		t.Error("importing private key: " + e.Error())
 681  		return
 682  	}
 683  	addr, e := w.Address(address)
 684  	if e != nil {
 685  		t.Error("privkey just imported missing: " + e.Error())
 686  		return
 687  	}
 688  	pka := addr.(PubKeyAddress)
 689  	// lookup address
 690  	pk2, e := pka.PrivKey()
 691  	if e != nil {
 692  		t.Error("error looking up key: " + e.Error())
 693  	}
 694  	if !reflect.DeepEqual(pk, pk2) {
 695  		t.Error("original and looked-up private keys do not match.")
 696  		return
 697  	}
 698  	// verify that the sync height now match the (smaller) import height.
 699  	if _, h := w.SyncedTo(); h != importHeight {
 700  		t.Errorf("After import sync height %v does not match expected %v.", h, importHeight)
 701  		return
 702  	}
 703  	// serialise and deseralise and check still there.
 704  	// Test (de)serialization of wallet.
 705  	buf := new(bytes.Buffer)
 706  	_, e = w.WriteTo(buf)
 707  	if e != nil {
 708  		t.Errorf("Cannot write wallet: %v", e)
 709  		return
 710  	}
 711  	w2 := new(Store)
 712  	_, e = w2.ReadFrom(buf)
 713  	if e != nil {
 714  		t.Errorf("Cannot read wallet: %v", e)
 715  		return
 716  	}
 717  	// Verify that the  sync height match expected after the reserialization.
 718  	if _, h := w2.SyncedTo(); h != importHeight {
 719  		t.Errorf("After reserialization sync height %v does not match expected %v.", h, importHeight)
 720  		return
 721  	}
 722  	// Mark imported address as partially synced with a block somewhere inbetween
 723  	// the import height and the chain height.
 724  	partialHeight := (createHeight-importHeight)/2 + importHeight
 725  	if e = w2.SetSyncStatus(address, PartialSync(partialHeight)); E.Chk(e) {
 726  		t.Errorf("Cannot mark address partially synced: %v", e)
 727  		return
 728  	}
 729  	if _, h := w2.SyncedTo(); h != partialHeight {
 730  		t.Errorf("After address partial sync, sync height %v does not match expected %v.", h, partialHeight)
 731  		return
 732  	}
 733  	// Test serialization with the partial sync.
 734  	buf.Reset()
 735  	_, e = w2.WriteTo(buf)
 736  	if e != nil {
 737  		t.Errorf("Cannot write wallet: %v", e)
 738  		return
 739  	}
 740  	w3 := new(Store)
 741  	_, e = w3.ReadFrom(buf)
 742  	if e != nil {
 743  		t.Errorf("Cannot read wallet: %v", e)
 744  		return
 745  	}
 746  	// Test correct partial height after serialization.
 747  	if _, h := w3.SyncedTo(); h != partialHeight {
 748  		t.Errorf("After address partial sync and reserialization, sync height %v does not match expected %v.",
 749  			h, partialHeight,
 750  		)
 751  		return
 752  	}
 753  	// Mark imported address as not synced at all, and verify sync height is now
 754  	// the import height.
 755  	if e = w3.SetSyncStatus(address, Unsynced(0)); E.Chk(e) {
 756  		t.Errorf("Cannot mark address synced: %v", e)
 757  		return
 758  	}
 759  	if _, h := w3.SyncedTo(); h != importHeight {
 760  		t.Errorf("After address unsync, sync height %v does not match expected %v.", h, importHeight)
 761  		return
 762  	}
 763  	// Mark imported address as synced with the recently-seen blocks, and verify
 764  	// that the sync height now equals the most recent block (the one at wallet
 765  	// creation).
 766  	if e = w3.SetSyncStatus(address, FullSync{}); E.Chk(e) {
 767  		t.Errorf("Cannot mark address synced: %v", e)
 768  		return
 769  	}
 770  	if _, h := w3.SyncedTo(); h != createHeight {
 771  		t.Errorf("After address sync, sync height %v does not match expected %v.", h, createHeight)
 772  		return
 773  	}
 774  	if e = w3.Unlock([]byte("banana")); E.Chk(e) {
 775  		t.Errorf("Can't unlock deserialised wallet: %v", e)
 776  		return
 777  	}
 778  	addr3, e := w3.Address(address)
 779  	if e != nil {
 780  		t.Error("privkey in deserialised wallet missing : " +
 781  			e.Error(),
 782  		)
 783  		return
 784  	}
 785  	pka3 := addr3.(PubKeyAddress)
 786  	// lookup address
 787  	pk2, e = pka3.PrivKey()
 788  	if e != nil {
 789  		t.Error("error looking up key in deserialized wallet: " + e.Error())
 790  	}
 791  	if !reflect.DeepEqual(pk, pk2) {
 792  		t.Error("original and deserialized private keys do not match.")
 793  		return
 794  	}
 795  }
 796  func TestImportScript(t *testing.T) {
 797  	createHeight := int32(100)
 798  	createdAt := makeBS(createHeight)
 799  	w, e := New(dummyDir, "A wallet for testing.",
 800  		[]byte("banana"), tstNetParams, createdAt,
 801  	)
 802  	if e != nil {
 803  		t.Error("ScriptError creating new wallet: " + e.Error())
 804  		return
 805  	}
 806  	if e = w.Unlock([]byte("banana")); E.Chk(e) {
 807  		t.Errorf("Can't unlock original wallet: %v", e)
 808  		return
 809  	}
 810  	// verify that the entire wallet's sync height matches the
 811  	// expected createHeight.
 812  	if _, h := w.SyncedTo(); h != createHeight {
 813  		t.Errorf("Initial sync height %v does not match expected %v.", h, createHeight)
 814  		return
 815  	}
 816  	script := []byte{txscript.OP_TRUE, txscript.OP_DUP,
 817  		txscript.OP_DROP,
 818  	}
 819  	importHeight := int32(50)
 820  	stamp := makeBS(importHeight)
 821  	address, e := w.ImportScript(script, stamp)
 822  	if e != nil {
 823  		t.Error("error importing script: " + e.Error())
 824  		return
 825  	}
 826  	// lookup address
 827  	ainfo, e := w.Address(address)
 828  	if e != nil {
 829  		t.Error("error looking up script: " + e.Error())
 830  	}
 831  	sinfo := ainfo.(ScriptAddress)
 832  	if !bytes.Equal(script, sinfo.Script()) {
 833  		t.Error("original and looked-up script do not match.")
 834  		return
 835  	}
 836  	if sinfo.ScriptClass() != txscript.NonStandardTy {
 837  		t.Error("script type incorrect.")
 838  		return
 839  	}
 840  	if sinfo.RequiredSigs() != 0 {
 841  		t.Error("required sigs funny number")
 842  		return
 843  	}
 844  	if len(sinfo.Addresses()) != 0 {
 845  		t.Error("addresses in bogus script.")
 846  		return
 847  	}
 848  	if sinfo.Address().EncodeAddress() != address.EncodeAddress() {
 849  		t.Error("script address doesn't match entry.")
 850  		return
 851  	}
 852  	if string(sinfo.Address().ScriptAddress()) != sinfo.AddrHash() {
 853  		t.Error("script hash doesn't match address.")
 854  		return
 855  	}
 856  	if sinfo.FirstBlock() != importHeight {
 857  		t.Error("funny first block")
 858  		return
 859  	}
 860  	if !sinfo.Imported() {
 861  		t.Error("imported script info not imported.")
 862  		return
 863  	}
 864  	if sinfo.Change() {
 865  		t.Error("imported script is change.")
 866  		return
 867  	}
 868  	if sinfo.Compressed() {
 869  		t.Error("imported script is compressed.")
 870  		return
 871  	}
 872  	// verify that the sync height now match the (smaller) import height.
 873  	if _, h := w.SyncedTo(); h != importHeight {
 874  		t.Errorf("After import sync height %v does not match expected %v.", h, importHeight)
 875  		return
 876  	}
 877  	// Chk that it's included along with the active payment addresses.
 878  	found := false
 879  	for _, wa := range w.SortedActiveAddresses() {
 880  		if wa.Address() == address {
 881  			found = true
 882  			break
 883  		}
 884  	}
 885  	if !found {
 886  		t.Errorf("Imported script address was not returned with sorted active payment addresses.")
 887  		return
 888  	}
 889  	if _, ok := w.ActiveAddresses()[address]; !ok {
 890  		t.Errorf("Imported script address was not returned with unsorted active payment addresses.")
 891  		return
 892  	}
 893  	// serialise and deseralise and check still there.
 894  	// Test (de)serialization of wallet.
 895  	buf := new(bytes.Buffer)
 896  	_, e = w.WriteTo(buf)
 897  	if e != nil {
 898  		t.Errorf("Cannot write wallet: %v", e)
 899  		return
 900  	}
 901  	w2 := new(Store)
 902  	_, e = w2.ReadFrom(buf)
 903  	if e != nil {
 904  		t.Errorf("Cannot read wallet: %v", e)
 905  		return
 906  	}
 907  	// Verify that the sync height matches expected after the reserialization.
 908  	if _, h := w2.SyncedTo(); h != importHeight {
 909  		t.Errorf("After reserialization sync height %v does not match expected %v.", h, importHeight)
 910  		return
 911  	}
 912  	// lookup address
 913  	ainfo2, e := w2.Address(address)
 914  	if e != nil {
 915  		t.Error("error looking up info in deserialized wallet: " + e.Error())
 916  	}
 917  	sinfo2 := ainfo2.(ScriptAddress)
 918  	// Chk all the same again. We can't use reflect.DeepEquals since
 919  	// the internals have pointers back to the wallet struct.
 920  	if sinfo2.Address().EncodeAddress() != address.EncodeAddress() {
 921  		t.Error("script address doesn't match entry.")
 922  		return
 923  	}
 924  	if string(sinfo2.Address().ScriptAddress()) != sinfo2.AddrHash() {
 925  		t.Error("script hash doesn't match address.")
 926  		return
 927  	}
 928  	if sinfo2.FirstBlock() != importHeight {
 929  		t.Error("funny first block")
 930  		return
 931  	}
 932  	if !sinfo2.Imported() {
 933  		t.Error("imported script info not imported.")
 934  		return
 935  	}
 936  	if sinfo2.Change() {
 937  		t.Error("imported script is change.")
 938  		return
 939  	}
 940  	if sinfo2.Compressed() {
 941  		t.Error("imported script is compressed.")
 942  		return
 943  	}
 944  	if !bytes.Equal(sinfo.Script(), sinfo2.Script()) {
 945  		t.Errorf("original and serailised scriptinfo scripts "+
 946  			"don't match %s != %s", spew.Sdump(sinfo.Script()),
 947  			spew.Sdump(sinfo2.Script()),
 948  		)
 949  	}
 950  	if sinfo.ScriptClass() != sinfo2.ScriptClass() {
 951  		t.Errorf("original and serailised scriptinfo class "+
 952  			"don't match: %s != %s", sinfo.ScriptClass(),
 953  			sinfo2.ScriptClass(),
 954  		)
 955  		return
 956  	}
 957  	if !reflect.DeepEqual(sinfo.Addresses(), sinfo2.Addresses()) {
 958  		t.Errorf("original and serailised scriptinfo addresses "+
 959  			"don't match (%s) != (%s)", spew.Sdump(sinfo.Addresses),
 960  			spew.Sdump(sinfo2.Addresses()),
 961  		)
 962  		return
 963  	}
 964  	// if sinfo.RequiredSigs() != sinfo.RequiredSigs() {
 965  	// 	t.Errorf("original and serailised scriptinfo requiredsigs "+
 966  	// 		"don't match %d != %d", sinfo.RequiredSigs(),
 967  	// 		sinfo2.RequiredSigs())
 968  	// 	return
 969  	// }
 970  	// Chk that it's included along with the active payment addresses.
 971  	found = false
 972  	for _, wa := range w.SortedActiveAddresses() {
 973  		if wa.Address() == address {
 974  			found = true
 975  			break
 976  		}
 977  	}
 978  	if !found {
 979  		t.Errorf("After reserialiation, imported script address was not returned with sorted " +
 980  			"active payment addresses.",
 981  		)
 982  		return
 983  	}
 984  	if _, ok := w.ActiveAddresses()[address]; !ok {
 985  		t.Errorf("After reserialiation, imported script address was not returned with unsorted " +
 986  			"active payment addresses.",
 987  		)
 988  		return
 989  	}
 990  	// Mark imported address as partially synced with a block somewhere inbetween
 991  	// the import height and the chain height.
 992  	partialHeight := (createHeight-importHeight)/2 + importHeight
 993  	if e = w2.SetSyncStatus(address, PartialSync(partialHeight)); E.Chk(e) {
 994  		t.Errorf("Cannot mark address partially synced: %v", e)
 995  		return
 996  	}
 997  	if _, h := w2.SyncedTo(); h != partialHeight {
 998  		t.Errorf("After address partial sync, sync height %v does not match expected %v.", h, partialHeight)
 999  		return
1000  	}
1001  	// Test serialization with the partial sync.
1002  	buf.Reset()
1003  	_, e = w2.WriteTo(buf)
1004  	if e != nil {
1005  		t.Errorf("Cannot write wallet: %v", e)
1006  		return
1007  	}
1008  	w3 := new(Store)
1009  	_, e = w3.ReadFrom(buf)
1010  	if e != nil {
1011  		t.Errorf("Cannot read wallet: %v", e)
1012  		return
1013  	}
1014  	// Test correct partial height after serialization.
1015  	if _, h := w3.SyncedTo(); h != partialHeight {
1016  		t.Errorf("After address partial sync and reserialization, sync height %v does not match expected %v.",
1017  			h, partialHeight,
1018  		)
1019  		return
1020  	}
1021  	// Mark imported address as not synced at all, and verify sync height is now
1022  	// the import height.
1023  	if e = w3.SetSyncStatus(address, Unsynced(0)); E.Chk(e) {
1024  		t.Errorf("Cannot mark address synced: %v", e)
1025  		return
1026  	}
1027  	if _, h := w3.SyncedTo(); h != importHeight {
1028  		t.Errorf("After address unsync, sync height %v does not match expected %v.", h, importHeight)
1029  		return
1030  	}
1031  	// Mark imported address as synced with the recently-seen blocks, and verify
1032  	// that the sync height now equals the most recent block (the one at wallet
1033  	// creation).
1034  	if e = w3.SetSyncStatus(address, FullSync{}); E.Chk(e) {
1035  		t.Errorf("Cannot mark address synced: %v", e)
1036  		return
1037  	}
1038  	if _, h := w3.SyncedTo(); h != createHeight {
1039  		t.Errorf("After address sync, sync height %v does not match expected %v.", h, createHeight)
1040  		return
1041  	}
1042  	if e = w3.Unlock([]byte("banana")); E.Chk(e) {
1043  		t.Errorf("Can't unlock deserialised wallet: %v", e)
1044  		return
1045  	}
1046  }
1047  func TestChangePassphrase(t *testing.T) {
1048  	createdAt := makeBS(0)
1049  	var e error
1050  	var w *Store
1051  	w, e = New(dummyDir, "A wallet for testing.",
1052  		[]byte("banana"), tstNetParams, createdAt,
1053  	)
1054  	if e != nil {
1055  		t.Error("ScriptError creating new wallet: " + e.Error())
1056  		return
1057  	}
1058  	// Changing the passphrase with a locked wallet must fail with ErrWalletLocked.
1059  	if e = w.ChangePassphrase([]byte("potato")); e != ErrLocked {
1060  		t.Errorf("Changing passphrase on a locked wallet did not fail correctly: %v", e)
1061  		return
1062  	}
1063  	// Unlock wallet so the passphrase can be changed.
1064  	if e = w.Unlock([]byte("banana")); E.Chk(e) {
1065  		t.Errorf("Cannot unlock: %v", e)
1066  		return
1067  	}
1068  	// Get root address and its private key.  This is compared to the private
1069  	// key post passphrase change.
1070  	rootAddr := w.LastChainedAddress()
1071  	rootAddrInfo, e := w.Address(rootAddr)
1072  	if e != nil {
1073  		t.Error("can't find root address: " + e.Error())
1074  		return
1075  	}
1076  	rapka := rootAddrInfo.(PubKeyAddress)
1077  	rootPrivKey, e := rapka.PrivKey()
1078  	if e != nil {
1079  		t.Errorf("Cannot get root address' private key: %v", e)
1080  		return
1081  	}
1082  	// Change passphrase.
1083  	if e = w.ChangePassphrase([]byte("potato")); E.Chk(e) {
1084  		t.Errorf("Changing passphrase failed: %v", e)
1085  		return
1086  	}
1087  	// Wallet should still be unlocked.
1088  	if w.IsLocked() {
1089  		t.Errorf("Wallet should be unlocked after passphrase change.")
1090  		return
1091  	}
1092  	// Lock it.
1093  	if e = w.Lock(); E.Chk(e) {
1094  		t.Errorf("Cannot lock wallet after passphrase change: %v", e)
1095  		return
1096  	}
1097  	// Unlock with old passphrase.  This must fail with ErrWrongPassphrase.
1098  	if e = w.Unlock([]byte("banana")); e != ErrWrongPassphrase {
1099  		t.Errorf("Unlocking with old passphrases did not fail correctly: %v", e)
1100  		return
1101  	}
1102  	// Unlock with new passphrase.  This must succeed.
1103  	if e = w.Unlock([]byte("potato")); E.Chk(e) {
1104  		t.Errorf("Unlocking with new passphrase failed: %v", e)
1105  		return
1106  	}
1107  	// Get root address' private key again.
1108  	rootAddrInfo2, e := w.Address(rootAddr)
1109  	if e != nil {
1110  		t.Error("can't find root address: " + e.Error())
1111  		return
1112  	}
1113  	rapka2 := rootAddrInfo2.(PubKeyAddress)
1114  	rootPrivKey2, e := rapka2.PrivKey()
1115  	if e != nil {
1116  		t.Errorf("Cannot get root address' private key after passphrase change: %v", e)
1117  		return
1118  	}
1119  	// Private keys must match.
1120  	if !reflect.DeepEqual(rootPrivKey, rootPrivKey2) {
1121  		t.Errorf("Private keys before and after unlock differ.")
1122  		return
1123  	}
1124  }
1125