Skip to content

Commit 611ab30

Browse files
committed
Introduce KeyOriginInfo for fingerprint + path
1 parent 5df6f08 commit 611ab30

File tree

3 files changed

+34
-28
lines changed

3 files changed

+34
-28
lines changed

src/rpc/rawtransaction.cpp

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1460,11 +1460,8 @@ UniValue decodepsbt(const JSONRPCRequest& request)
14601460
UniValue keypath(UniValue::VOBJ);
14611461
keypath.pushKV("pubkey", HexStr(entry.first));
14621462

1463-
uint32_t fingerprint = entry.second.at(0);
1464-
keypath.pushKV("master_fingerprint", strprintf("%08x", bswap_32(fingerprint)));
1465-
1466-
entry.second.erase(entry.second.begin());
1467-
keypath.pushKV("path", WriteHDKeypath(entry.second));
1463+
keypath.pushKV("master_fingerprint", strprintf("%08x", ReadBE32(entry.second.fingerprint)));
1464+
keypath.pushKV("path", WriteHDKeypath(entry.second.path));
14681465
keypaths.push_back(keypath);
14691466
}
14701467
in.pushKV("bip32_derivs", keypaths);
@@ -1522,12 +1519,8 @@ UniValue decodepsbt(const JSONRPCRequest& request)
15221519
for (auto entry : output.hd_keypaths) {
15231520
UniValue keypath(UniValue::VOBJ);
15241521
keypath.pushKV("pubkey", HexStr(entry.first));
1525-
1526-
uint32_t fingerprint = entry.second.at(0);
1527-
keypath.pushKV("master_fingerprint", strprintf("%08x", bswap_32(fingerprint)));
1528-
1529-
entry.second.erase(entry.second.begin());
1530-
keypath.pushKV("path", WriteHDKeypath(entry.second));
1522+
keypath.pushKV("master_fingerprint", strprintf("%08x", ReadBE32(entry.second.fingerprint)));
1523+
keypath.pushKV("path", WriteHDKeypath(entry.second.path));
15311524
keypaths.push_back(keypath);
15321525
}
15331526
out.pushKV("bip32_derivs", keypaths);

src/script/sign.h

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ class CTransaction;
2020

2121
struct CMutableTransaction;
2222

23+
struct KeyOriginInfo
24+
{
25+
unsigned char fingerprint[4];
26+
std::vector<uint32_t> path;
27+
};
28+
2329
/** An interface to be implemented by keystores that support signing. */
2430
class SigningProvider
2531
{
@@ -155,7 +161,7 @@ void UnserializeFromVector(Stream& s, X&... args)
155161

156162
// Deserialize HD keypaths into a map
157163
template<typename Stream>
158-
void DeserializeHDKeypaths(Stream& s, const std::vector<unsigned char>& key, std::map<CPubKey, std::vector<uint32_t>>& hd_keypaths)
164+
void DeserializeHDKeypaths(Stream& s, const std::vector<unsigned char>& key, std::map<CPubKey, KeyOriginInfo>& hd_keypaths)
159165
{
160166
// Make sure that the key is the size of pubkey + 1
161167
if (key.size() != CPubKey::PUBLIC_KEY_SIZE + 1 && key.size() != CPubKey::COMPRESSED_PUBLIC_KEY_SIZE + 1) {
@@ -172,25 +178,31 @@ void DeserializeHDKeypaths(Stream& s, const std::vector<unsigned char>& key, std
172178

173179
// Read in key path
174180
uint64_t value_len = ReadCompactSize(s);
175-
std::vector<uint32_t> keypath;
176-
for (unsigned int i = 0; i < value_len; i += sizeof(uint32_t)) {
181+
if (value_len % 4 || value_len == 0) {
182+
throw std::ios_base::failure("Invalid length for HD key path");
183+
}
184+
185+
KeyOriginInfo keypath;
186+
s >> keypath.fingerprint;
187+
for (unsigned int i = 4; i < value_len; i += sizeof(uint32_t)) {
177188
uint32_t index;
178189
s >> index;
179-
keypath.push_back(index);
190+
keypath.path.push_back(index);
180191
}
181192

182193
// Add to map
183-
hd_keypaths.emplace(pubkey, keypath);
194+
hd_keypaths.emplace(pubkey, std::move(keypath));
184195
}
185196

186197
// Serialize HD keypaths to a stream from a map
187198
template<typename Stream>
188-
void SerializeHDKeypaths(Stream& s, const std::map<CPubKey, std::vector<uint32_t>>& hd_keypaths, uint8_t type)
199+
void SerializeHDKeypaths(Stream& s, const std::map<CPubKey, KeyOriginInfo>& hd_keypaths, uint8_t type)
189200
{
190201
for (auto keypath_pair : hd_keypaths) {
191202
SerializeToVector(s, type, MakeSpan(keypath_pair.first));
192-
WriteCompactSize(s, keypath_pair.second.size() * sizeof(uint32_t));
193-
for (auto& path : keypath_pair.second) {
203+
WriteCompactSize(s, (keypath_pair.second.path.size() + 1) * sizeof(uint32_t));
204+
s << keypath_pair.second.fingerprint;
205+
for (const auto& path : keypath_pair.second.path) {
194206
s << path;
195207
}
196208
}
@@ -205,7 +217,7 @@ struct PSBTInput
205217
CScript witness_script;
206218
CScript final_script_sig;
207219
CScriptWitness final_script_witness;
208-
std::map<CPubKey, std::vector<uint32_t>> hd_keypaths;
220+
std::map<CPubKey, KeyOriginInfo> hd_keypaths;
209221
std::map<CKeyID, SigPair> partial_sigs;
210222
std::map<std::vector<unsigned char>, std::vector<unsigned char>> unknown;
211223
int sighash_type = 0;
@@ -413,7 +425,7 @@ struct PSBTOutput
413425
{
414426
CScript redeem_script;
415427
CScript witness_script;
416-
std::map<CPubKey, std::vector<uint32_t>> hd_keypaths;
428+
std::map<CPubKey, KeyOriginInfo> hd_keypaths;
417429
std::map<std::vector<unsigned char>, std::vector<unsigned char>> unknown;
418430

419431
bool IsNull() const;

src/wallet/rpcwallet.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4464,7 +4464,7 @@ bool ParseHDKeypath(std::string keypath_str, std::vector<uint32_t>& keypath)
44644464
return true;
44654465
}
44664466

4467-
void AddKeypathToMap(const CWallet* pwallet, const CKeyID& keyID, std::map<CPubKey, std::vector<uint32_t>>& hd_keypaths)
4467+
void AddKeypathToMap(const CWallet* pwallet, const CKeyID& keyID, std::map<CPubKey, KeyOriginInfo>& hd_keypaths)
44684468
{
44694469
CPubKey vchPubKey;
44704470
if (!pwallet->GetPubKey(keyID, vchPubKey)) {
@@ -4475,22 +4475,23 @@ void AddKeypathToMap(const CWallet* pwallet, const CKeyID& keyID, std::map<CPubK
44754475
if (it != pwallet->mapKeyMetadata.end()) {
44764476
meta = it->second;
44774477
}
4478-
std::vector<uint32_t> keypath;
4478+
KeyOriginInfo info;
44794479
if (!meta.hdKeypath.empty()) {
4480-
if (!ParseHDKeypath(meta.hdKeypath, keypath)) {
4480+
if (!ParseHDKeypath(meta.hdKeypath, info.path)) {
44814481
throw JSONRPCError(RPC_INTERNAL_ERROR, "Internal keypath is broken");
44824482
}
44834483
// Get the proper master key id
44844484
CKey key;
44854485
pwallet->GetKey(meta.hd_seed_id, key);
44864486
CExtKey masterKey;
44874487
masterKey.SetSeed(key.begin(), key.size());
4488-
// Add to map
4489-
keypath.insert(keypath.begin(), ReadLE32(masterKey.key.GetPubKey().GetID().begin()));
4488+
// Compute identifier
4489+
CKeyID masterid = masterKey.key.GetPubKey().GetID();
4490+
std::copy(masterid.begin(), masterid.begin() + 4, info.fingerprint);
44904491
} else { // Single pubkeys get the master fingerprint of themselves
4491-
keypath.insert(keypath.begin(), ReadLE32(vchPubKey.GetID().begin()));
4492+
std::copy(keyID.begin(), keyID.begin() + 4, info.fingerprint);
44924493
}
4493-
hd_keypaths.emplace(vchPubKey, keypath);
4494+
hd_keypaths.emplace(vchPubKey, std::move(info));
44944495
}
44954496

44964497
bool FillPSBT(const CWallet* pwallet, PartiallySignedTransaction& psbtx, const CTransaction* txConst, int sighash_type, bool sign, bool bip32derivs)

0 commit comments

Comments
 (0)