1// Copyright (c) 2014 The btcsuite developers 2// Use of this source code is governed by an ISC 3// license that can be found in the LICENSE file. 4 5package hdkeychain_test 6 7import ( 8 "fmt" 9 10 "github.com/btcsuite/btcd/chaincfg" 11 "github.com/btcsuite/btcutil/hdkeychain" 12) 13 14// This example demonstrates how to generate a cryptographically random seed 15// then use it to create a new master node (extended key). 16func ExampleNewMaster() { 17 // Generate a random seed at the recommended length. 18 seed, err := hdkeychain.GenerateSeed(hdkeychain.RecommendedSeedLen) 19 if err != nil { 20 fmt.Println(err) 21 return 22 } 23 24 // Generate a new master node using the seed. 25 key, err := hdkeychain.NewMaster(seed, &chaincfg.MainNetParams) 26 if err != nil { 27 fmt.Println(err) 28 return 29 } 30 31 // Show that the generated master node extended key is private. 32 fmt.Println("Private Extended Key?:", key.IsPrivate()) 33 34 // Output: 35 // Private Extended Key?: true 36} 37 38// This example demonstrates the default hierarchical deterministic wallet 39// layout as described in BIP0032. 40func Example_defaultWalletLayout() { 41 // The default wallet layout described in BIP0032 is: 42 // 43 // Each account is composed of two keypair chains: an internal and an 44 // external one. The external keychain is used to generate new public 45 // addresses, while the internal keychain is used for all other 46 // operations (change addresses, generation addresses, ..., anything 47 // that doesn't need to be communicated). 48 // 49 // * m/iH/0/k 50 // corresponds to the k'th keypair of the external chain of account 51 // number i of the HDW derived from master m. 52 // * m/iH/1/k 53 // corresponds to the k'th keypair of the internal chain of account 54 // number i of the HDW derived from master m. 55 56 // Ordinarily this would either be read from some encrypted source 57 // and be decrypted or generated as the NewMaster example shows, but 58 // for the purposes of this example, the private extended key for the 59 // master node is being hard coded here. 60 master := "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jP" + 61 "PqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi" 62 63 // Start by getting an extended key instance for the master node. 64 // This gives the path: 65 // m 66 masterKey, err := hdkeychain.NewKeyFromString(master) 67 if err != nil { 68 fmt.Println(err) 69 return 70 } 71 72 // Derive the extended key for account 0. This gives the path: 73 // m/0H 74 acct0, err := masterKey.Derive(hdkeychain.HardenedKeyStart + 0) 75 if err != nil { 76 fmt.Println(err) 77 return 78 } 79 80 // Derive the extended key for the account 0 external chain. This 81 // gives the path: 82 // m/0H/0 83 acct0Ext, err := acct0.Derive(0) 84 if err != nil { 85 fmt.Println(err) 86 return 87 } 88 89 // Derive the extended key for the account 0 internal chain. This gives 90 // the path: 91 // m/0H/1 92 acct0Int, err := acct0.Derive(1) 93 if err != nil { 94 fmt.Println(err) 95 return 96 } 97 98 // At this point, acct0Ext and acct0Int are ready to derive the keys for 99 // the external and internal wallet chains. 100 101 // Derive the 10th extended key for the account 0 external chain. This 102 // gives the path: 103 // m/0H/0/10 104 acct0Ext10, err := acct0Ext.Derive(10) 105 if err != nil { 106 fmt.Println(err) 107 return 108 } 109 110 // Derive the 1st extended key for the account 0 internal chain. This 111 // gives the path: 112 // m/0H/1/0 113 acct0Int0, err := acct0Int.Derive(0) 114 if err != nil { 115 fmt.Println(err) 116 return 117 } 118 119 // Get and show the address associated with the extended keys for the 120 // main bitcoin network. 121 acct0ExtAddr, err := acct0Ext10.Address(&chaincfg.MainNetParams) 122 if err != nil { 123 fmt.Println(err) 124 return 125 } 126 acct0IntAddr, err := acct0Int0.Address(&chaincfg.MainNetParams) 127 if err != nil { 128 fmt.Println(err) 129 return 130 } 131 fmt.Println("Account 0 External Address 10:", acct0ExtAddr) 132 fmt.Println("Account 0 Internal Address 0:", acct0IntAddr) 133 134 // Output: 135 // Account 0 External Address 10: 1HVccubUT8iKTapMJ5AnNA4sLRN27xzQ4F 136 // Account 0 Internal Address 0: 1J5rebbkQaunJTUoNVREDbeB49DqMNFFXk 137} 138 139// This example demonstrates the audits use case in BIP0032. 140func Example_audits() { 141 // The audits use case described in BIP0032 is: 142 // 143 // In case an auditor needs full access to the list of incoming and 144 // outgoing payments, one can share all account public extended keys. 145 // This will allow the auditor to see all transactions from and to the 146 // wallet, in all accounts, but not a single secret key. 147 // 148 // * N(m/*) 149 // corresponds to the neutered master extended key (also called 150 // the master public extended key) 151 152 // Ordinarily this would either be read from some encrypted source 153 // and be decrypted or generated as the NewMaster example shows, but 154 // for the purposes of this example, the private extended key for the 155 // master node is being hard coded here. 156 master := "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jP" + 157 "PqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi" 158 159 // Start by getting an extended key instance for the master node. 160 // This gives the path: 161 // m 162 masterKey, err := hdkeychain.NewKeyFromString(master) 163 if err != nil { 164 fmt.Println(err) 165 return 166 } 167 168 // Neuter the master key to generate a master public extended key. This 169 // gives the path: 170 // N(m/*) 171 masterPubKey, err := masterKey.Neuter() 172 if err != nil { 173 fmt.Println(err) 174 return 175 } 176 177 // Share the master public extended key with the auditor. 178 fmt.Println("Audit key N(m/*):", masterPubKey) 179 180 // Output: 181 // Audit key N(m/*): xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8 182} 183