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