upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/key.h
diff options
context:
space:
mode:
authorBitflash <btf01@proton.me>2026-08-01 17:53:17 -0300
committerGitHub <noreply@github.com>2026-08-01 17:53:17 -0300
commitce59d8c72c667ce638bd12f37db26d8b3408a5d2 (patch)
tree95c62a0d0cc0a21bc3349264ce0a3c949deb32c3 /src/key.h
parent593cf346dbce0a8ce46a13a73a4f78ddd044ab52 (diff)
wallet: derive the key pool from a seed, so a phrase could bring it back (#93)
Adds BIP32 derivation behind the wallet key pool, with no user-facing way to create a seed yet. wallet.dat gains hdmaster/hdchaincode/hdnext; the mnemonic is never stored. TopUpKeyPool derives m/n' when a seed exists and falls back to a random key, with a log line, if derivation fails. New -selftest=wallet-hd, wired into make tests on both platforms.
Diffstat (limited to 'src/key.h')
-rw-r--r--src/key.h34
1 files changed, 34 insertions, 0 deletions
diff --git a/src/key.h b/src/key.h
index 26e1ae2..6cc2a24 100644
--- a/src/key.h
+++ b/src/key.h
@@ -86,6 +86,40 @@ public:
86 return true; 86 return true;
87 } 87 }
88 88
89 // Load a raw 32-byte scalar, the form BIP32 derivation produces.
90 //
91 // SetPrivKey above takes DER and cannot be used for this: handing it a
92 // scalar makes d2i_ECPrivateKey fail, and if the caller ignores the return
93 // value -- as one attempt at this did -- the key is left with no material
94 // at all and the address it produces has no private half. Coins paid there
95 // are gone. Hence a separate entry point rather than a looser SetPrivKey.
96 //
97 // The public half is computed here rather than read from anywhere:
98 // pub = G * secret.
99 bool SetSecret(const std::vector<unsigned char>& vchSecret)
100 {
101 if (vchSecret.size() != 32)
102 return false;
103
104 bool fOk = false;
105 BIGNUM* bn = BN_bin2bn(&vchSecret[0], 32, NULL);
106 EC_POINT* pubkey = NULL;
107 if (bn && EC_KEY_set_private_key(pkey, bn))
108 {
109 const EC_GROUP* group = EC_KEY_get0_group(pkey);
110 pubkey = EC_POINT_new(group);
111 if (pubkey &&
112 EC_POINT_mul(group, pubkey, bn, NULL, NULL, NULL) &&
113 EC_KEY_set_public_key(pkey, pubkey))
114 fOk = true;
115 }
116 if (pubkey)
117 EC_POINT_free(pubkey);
118 if (bn)
119 BN_clear_free(bn); // it held the secret
120 return fOk;
121 }
122
89 CPrivKey GetPrivKey() const 123 CPrivKey GetPrivKey() const
90 { 124 {
91 unsigned int nSize = i2d_ECPrivateKey(pkey, NULL); 125 unsigned int nSize = i2d_ECPrivateKey(pkey, NULL);