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