Introduce KeyOriginInfo for fingerprint + path
This commit is contained in:
parent
5df6f089b5
commit
611ab307fb
3 changed files with 34 additions and 28 deletions
|
@ -1460,11 +1460,8 @@ UniValue decodepsbt(const JSONRPCRequest& request)
|
|||
UniValue keypath(UniValue::VOBJ);
|
||||
keypath.pushKV("pubkey", HexStr(entry.first));
|
||||
|
||||
uint32_t fingerprint = entry.second.at(0);
|
||||
keypath.pushKV("master_fingerprint", strprintf("%08x", bswap_32(fingerprint)));
|
||||
|
||||
entry.second.erase(entry.second.begin());
|
||||
keypath.pushKV("path", WriteHDKeypath(entry.second));
|
||||
keypath.pushKV("master_fingerprint", strprintf("%08x", ReadBE32(entry.second.fingerprint)));
|
||||
keypath.pushKV("path", WriteHDKeypath(entry.second.path));
|
||||
keypaths.push_back(keypath);
|
||||
}
|
||||
in.pushKV("bip32_derivs", keypaths);
|
||||
|
@ -1522,12 +1519,8 @@ UniValue decodepsbt(const JSONRPCRequest& request)
|
|||
for (auto entry : output.hd_keypaths) {
|
||||
UniValue keypath(UniValue::VOBJ);
|
||||
keypath.pushKV("pubkey", HexStr(entry.first));
|
||||
|
||||
uint32_t fingerprint = entry.second.at(0);
|
||||
keypath.pushKV("master_fingerprint", strprintf("%08x", bswap_32(fingerprint)));
|
||||
|
||||
entry.second.erase(entry.second.begin());
|
||||
keypath.pushKV("path", WriteHDKeypath(entry.second));
|
||||
keypath.pushKV("master_fingerprint", strprintf("%08x", ReadBE32(entry.second.fingerprint)));
|
||||
keypath.pushKV("path", WriteHDKeypath(entry.second.path));
|
||||
keypaths.push_back(keypath);
|
||||
}
|
||||
out.pushKV("bip32_derivs", keypaths);
|
||||
|
|
|
@ -20,6 +20,12 @@ class CTransaction;
|
|||
|
||||
struct CMutableTransaction;
|
||||
|
||||
struct KeyOriginInfo
|
||||
{
|
||||
unsigned char fingerprint[4];
|
||||
std::vector<uint32_t> path;
|
||||
};
|
||||
|
||||
/** An interface to be implemented by keystores that support signing. */
|
||||
class SigningProvider
|
||||
{
|
||||
|
@ -155,7 +161,7 @@ void UnserializeFromVector(Stream& s, X&... args)
|
|||
|
||||
// Deserialize HD keypaths into a map
|
||||
template<typename Stream>
|
||||
void DeserializeHDKeypaths(Stream& s, const std::vector<unsigned char>& key, std::map<CPubKey, std::vector<uint32_t>>& hd_keypaths)
|
||||
void DeserializeHDKeypaths(Stream& s, const std::vector<unsigned char>& key, std::map<CPubKey, KeyOriginInfo>& hd_keypaths)
|
||||
{
|
||||
// Make sure that the key is the size of pubkey + 1
|
||||
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
|
|||
|
||||
// Read in key path
|
||||
uint64_t value_len = ReadCompactSize(s);
|
||||
std::vector<uint32_t> keypath;
|
||||
for (unsigned int i = 0; i < value_len; i += sizeof(uint32_t)) {
|
||||
if (value_len % 4 || value_len == 0) {
|
||||
throw std::ios_base::failure("Invalid length for HD key path");
|
||||
}
|
||||
|
||||
KeyOriginInfo keypath;
|
||||
s >> keypath.fingerprint;
|
||||
for (unsigned int i = 4; i < value_len; i += sizeof(uint32_t)) {
|
||||
uint32_t index;
|
||||
s >> index;
|
||||
keypath.push_back(index);
|
||||
keypath.path.push_back(index);
|
||||
}
|
||||
|
||||
// Add to map
|
||||
hd_keypaths.emplace(pubkey, keypath);
|
||||
hd_keypaths.emplace(pubkey, std::move(keypath));
|
||||
}
|
||||
|
||||
// Serialize HD keypaths to a stream from a map
|
||||
template<typename Stream>
|
||||
void SerializeHDKeypaths(Stream& s, const std::map<CPubKey, std::vector<uint32_t>>& hd_keypaths, uint8_t type)
|
||||
void SerializeHDKeypaths(Stream& s, const std::map<CPubKey, KeyOriginInfo>& hd_keypaths, uint8_t type)
|
||||
{
|
||||
for (auto keypath_pair : hd_keypaths) {
|
||||
SerializeToVector(s, type, MakeSpan(keypath_pair.first));
|
||||
WriteCompactSize(s, keypath_pair.second.size() * sizeof(uint32_t));
|
||||
for (auto& path : keypath_pair.second) {
|
||||
WriteCompactSize(s, (keypath_pair.second.path.size() + 1) * sizeof(uint32_t));
|
||||
s << keypath_pair.second.fingerprint;
|
||||
for (const auto& path : keypath_pair.second.path) {
|
||||
s << path;
|
||||
}
|
||||
}
|
||||
|
@ -205,7 +217,7 @@ struct PSBTInput
|
|||
CScript witness_script;
|
||||
CScript final_script_sig;
|
||||
CScriptWitness final_script_witness;
|
||||
std::map<CPubKey, std::vector<uint32_t>> hd_keypaths;
|
||||
std::map<CPubKey, KeyOriginInfo> hd_keypaths;
|
||||
std::map<CKeyID, SigPair> partial_sigs;
|
||||
std::map<std::vector<unsigned char>, std::vector<unsigned char>> unknown;
|
||||
int sighash_type = 0;
|
||||
|
@ -413,7 +425,7 @@ struct PSBTOutput
|
|||
{
|
||||
CScript redeem_script;
|
||||
CScript witness_script;
|
||||
std::map<CPubKey, std::vector<uint32_t>> hd_keypaths;
|
||||
std::map<CPubKey, KeyOriginInfo> hd_keypaths;
|
||||
std::map<std::vector<unsigned char>, std::vector<unsigned char>> unknown;
|
||||
|
||||
bool IsNull() const;
|
||||
|
|
|
@ -4464,7 +4464,7 @@ bool ParseHDKeypath(std::string keypath_str, std::vector<uint32_t>& keypath)
|
|||
return true;
|
||||
}
|
||||
|
||||
void AddKeypathToMap(const CWallet* pwallet, const CKeyID& keyID, std::map<CPubKey, std::vector<uint32_t>>& hd_keypaths)
|
||||
void AddKeypathToMap(const CWallet* pwallet, const CKeyID& keyID, std::map<CPubKey, KeyOriginInfo>& hd_keypaths)
|
||||
{
|
||||
CPubKey vchPubKey;
|
||||
if (!pwallet->GetPubKey(keyID, vchPubKey)) {
|
||||
|
@ -4475,9 +4475,9 @@ void AddKeypathToMap(const CWallet* pwallet, const CKeyID& keyID, std::map<CPubK
|
|||
if (it != pwallet->mapKeyMetadata.end()) {
|
||||
meta = it->second;
|
||||
}
|
||||
std::vector<uint32_t> keypath;
|
||||
KeyOriginInfo info;
|
||||
if (!meta.hdKeypath.empty()) {
|
||||
if (!ParseHDKeypath(meta.hdKeypath, keypath)) {
|
||||
if (!ParseHDKeypath(meta.hdKeypath, info.path)) {
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Internal keypath is broken");
|
||||
}
|
||||
// Get the proper master key id
|
||||
|
@ -4485,12 +4485,13 @@ void AddKeypathToMap(const CWallet* pwallet, const CKeyID& keyID, std::map<CPubK
|
|||
pwallet->GetKey(meta.hd_seed_id, key);
|
||||
CExtKey masterKey;
|
||||
masterKey.SetSeed(key.begin(), key.size());
|
||||
// Add to map
|
||||
keypath.insert(keypath.begin(), ReadLE32(masterKey.key.GetPubKey().GetID().begin()));
|
||||
// Compute identifier
|
||||
CKeyID masterid = masterKey.key.GetPubKey().GetID();
|
||||
std::copy(masterid.begin(), masterid.begin() + 4, info.fingerprint);
|
||||
} else { // Single pubkeys get the master fingerprint of themselves
|
||||
keypath.insert(keypath.begin(), ReadLE32(vchPubKey.GetID().begin()));
|
||||
std::copy(keyID.begin(), keyID.begin() + 4, info.fingerprint);
|
||||
}
|
||||
hd_keypaths.emplace(vchPubKey, keypath);
|
||||
hd_keypaths.emplace(vchPubKey, std::move(info));
|
||||
}
|
||||
|
||||
bool FillPSBT(const CWallet* pwallet, PartiallySignedTransaction& psbtx, const CTransaction* txConst, int sighash_type, bool sign, bool bip32derivs)
|
||||
|
|
Loading…
Add table
Reference in a new issue