example_test.go raw

   1  package hdkeychain_test
   2  
   3  import (
   4  	"fmt"
   5  	
   6  	"github.com/p9c/p9/pkg/chaincfg"
   7  	"github.com/p9c/p9/pkg/util/hdkeychain"
   8  )
   9  
  10  // This example demonstrates how to generate a cryptographically random seed then use it to create a new master node
  11  // (extended key).
  12  func ExampleNewMaster() {
  13  	// Generate a random seed at the recommended length.
  14  	seed, e := hdkeychain.GenerateSeed(hdkeychain.RecommendedSeedLen)
  15  	if e != nil {
  16  		return
  17  	}
  18  	// Generate a new master node using the seed.
  19  	key, e := hdkeychain.NewMaster(seed, &chaincfg.MainNetParams)
  20  	if e != nil {
  21  		return
  22  	}
  23  	// Show that the generated master node extended key is private.
  24  	fmt.Println("Private Extended Key?:", key.IsPrivate())
  25  	// Output:
  26  	// Private Extended Key?: true
  27  }
  28  
  29  // This example demonstrates the default hierarchical deterministic wallet layout as described in BIP0032.
  30  func Example_defaultWalletLayout() {
  31  	// The default wallet layout described in BIP0032 is:
  32  	//
  33  	// Each account is composed of two keypair chains: an internal and an external one. The external keychain is used to
  34  	// generate new public addresses, while the internal keychain is used for all other operations (change addresses,
  35  	// generation addresses, ..., anything that doesn't need to be communicated).
  36  	//
  37  	//   * m/iH/0/k
  38  	//
  39  	//   corresponds to the k'th keypair of the external chain of account number i of the HDW derived from master m.
  40  	//
  41  	//   * m/iH/1/k
  42  	//
  43  	//   corresponds to the k'th keypair of the internal chain of account number i of the HDW derived from master m.
  44  	//
  45  	// Ordinarily this would either be read from some encrypted source and be decrypted or generated as the NewMaster
  46  	// example shows, but for the purposes of this example, the private extended key for the master node is being hard
  47  	// coded here.
  48  	master := "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi"
  49  	// Start by getting an extended key instance for the master node. This gives the path: m
  50  	masterKey, e := hdkeychain.NewKeyFromString(master)
  51  	if e != nil {
  52  		return
  53  	}
  54  	// Derive the extended key for account 0.  This gives the path: m/0H
  55  	acct0, e := masterKey.Child(hdkeychain.HardenedKeyStart + 0)
  56  	if e != nil {
  57  		return
  58  	}
  59  	// Derive the extended key for the account 0 external chain.  This gives the path:   m/0H/0
  60  	acct0Ext, e := acct0.Child(0)
  61  	if e != nil {
  62  		return
  63  	}
  64  	// Derive the extended key for the account 0 internal chain.  This gives the path: m/0H/1
  65  	acct0Int, e := acct0.Child(1)
  66  	if e != nil {
  67  		return
  68  	}
  69  	// At this point, acct0Ext and acct0Int are ready to derive the keys for the external and internal wallet chains.
  70  	// Derive the 10th extended key for the account 0 external chain. This gives the path: m/0H/0/10
  71  	acct0Ext10, e := acct0Ext.Child(10)
  72  	if e != nil {
  73  		return
  74  	}
  75  	// Derive the 1st extended key for the account 0 internal chain.  This gives the path:   m/0H/1/0
  76  	acct0Int0, e := acct0Int.Child(0)
  77  	if e != nil {
  78  		return
  79  	}
  80  	// Get and show the address associated with the extended keys for the main bitcoin	network.
  81  	acct0ExtAddr, e := acct0Ext10.Address(&chaincfg.MainNetParams)
  82  	if e != nil {
  83  		return
  84  	}
  85  	acct0IntAddr, e := acct0Int0.Address(&chaincfg.MainNetParams)
  86  	if e != nil {
  87  		return
  88  	}
  89  	fmt.Println("Account 0 External Address 10:", acct0ExtAddr)
  90  	fmt.Println("Account 0 Internal Address 0:", acct0IntAddr)
  91  	// Output:
  92  	// Account 0 External Address 10: aV29NZpQZkh7ByDPhP4NR7nzx56crLAvTF
  93  	// Account 0 Internal Address 0: aUWmaTQVFwTV6wwQYvyyQRAvWeQmAorqAV
  94  }
  95  
  96  // This example demonstrates the audits use case in BIP0032.
  97  func Example_audits() {
  98  	// The audits use case described in BIP0032 is://
  99  	//
 100  	// In case an auditor needs full access to the list of incoming and outgoing payments, one can share all account
 101  	// public extended keys. This will allow the auditor to see all transactions from and to the wallet, in all
 102  	// accounts, but not a single secret key.
 103  	//
 104  	//   * N(m/*)
 105  	//
 106  	//   corresponds to the neutered master extended key (also called the master public extended key) Ordinarily this
 107  	//   would either be read from some encrypted source and be decrypted or generated as the NewMaster example shows, but
 108  	//   for the purposes of this example, the private extended key for the master node is being hard coded here.
 109  	master := "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi"
 110  	// Start by getting an extended key instance for the master node. This gives the path:
 111  	//
 112  	//   m
 113  	masterKey, e := hdkeychain.NewKeyFromString(master)
 114  	if e != nil {
 115  		return
 116  	}
 117  	// Neuter the master key to generate a master public extended key.  This gives the path:   N(m/*)
 118  	masterPubKey, e := masterKey.Neuter()
 119  	if e != nil {
 120  		return
 121  	}
 122  	// Share the master public extended key with the auditor.
 123  	fmt.Println("Audit key N(m/*):", masterPubKey)
 124  	// Output:
 125  	// Audit key N(m/*): xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8
 126  }
 127