Skip to content

Commit 9a86327

Browse files
committed
Merge bitcoin/bitcoin#22512: Consolidate XOnlyPubKey lookup hack
d9d3ec0 Consolidate XOnlyPubKey lookup hack (Andrew Chow) Pull request description: The places where we need to lookup information for a XOnlyPubKey currently implement a hack which makes both serializations of the full pubkey in order to try the CKeyIDs for the lookup functions. Instead of duplicating this everywhere it is needed, we can consolidate the CKeyID generation into a function, and then have wrappers around GetPubKey, GetKey, and GetKeyOrigin which takes the XOnlyPubKey, retrieves all of the CKeyIDs (using the new GetKeyIDs() function in XOnlyPubKey), and tries their respective underlying lookup function. Split from #22364 ACKs for top commit: S3RK: Code Review reACK d9d3ec0 Zero-1729: re-crACK d9d3ec0 theStack: re-ACK d9d3ec0 meshcollider: Code review + functional test run ACK d9d3ec0 Tree-SHA512: 21a7f6d37fad74483a38006f82b3558337fe9ed30e0b4392e6fff82c22251a42ac996b43f06cdaa9289ee34a768e181d87aa4208b5538e36ae4977954e1fa6a0
2 parents dc9ffb6 + d9d3ec0 commit 9a86327

File tree

5 files changed

+48
-23
lines changed

5 files changed

+48
-23
lines changed

src/pubkey.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,23 @@ XOnlyPubKey::XOnlyPubKey(Span<const unsigned char> bytes)
180180
std::copy(bytes.begin(), bytes.end(), m_keydata.begin());
181181
}
182182

183+
std::vector<CKeyID> XOnlyPubKey::GetKeyIDs() const
184+
{
185+
std::vector<CKeyID> out;
186+
// For now, use the old full pubkey-based key derivation logic. As it is indexed by
187+
// Hash160(full pubkey), we need to return both a version prefixed with 0x02, and one
188+
// with 0x03.
189+
unsigned char b[33] = {0x02};
190+
std::copy(m_keydata.begin(), m_keydata.end(), b + 1);
191+
CPubKey fullpubkey;
192+
fullpubkey.Set(b, b + 33);
193+
out.push_back(fullpubkey.GetID());
194+
b[0] = 0x03;
195+
fullpubkey.Set(b, b + 33);
196+
out.push_back(fullpubkey.GetID());
197+
return out;
198+
}
199+
183200
bool XOnlyPubKey::IsFullyValid() const
184201
{
185202
secp256k1_xonly_pubkey pubkey;

src/pubkey.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,11 @@ class XOnlyPubKey
267267
/** Construct a Taproot tweaked output point with this point as internal key. */
268268
std::optional<std::pair<XOnlyPubKey, bool>> CreateTapTweak(const uint256* merkle_root) const;
269269

270+
/** Returns a list of CKeyIDs for the CPubKeys that could have been used to create this XOnlyPubKey.
271+
* This is needed for key lookups since keys are indexed by CKeyID.
272+
*/
273+
std::vector<CKeyID> GetKeyIDs() const;
274+
270275
const unsigned char& operator[](int pos) const { return *(m_keydata.begin() + pos); }
271276
const unsigned char* data() const { return m_keydata.begin(); }
272277
static constexpr size_t size() { return decltype(m_keydata)::size(); }

src/script/descriptor.cpp

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1242,14 +1242,8 @@ std::unique_ptr<PubkeyProvider> InferXOnlyPubkey(const XOnlyPubKey& xkey, ParseS
12421242
CPubKey pubkey(full_key);
12431243
std::unique_ptr<PubkeyProvider> key_provider = std::make_unique<ConstPubkeyProvider>(0, pubkey, true);
12441244
KeyOriginInfo info;
1245-
if (provider.GetKeyOrigin(pubkey.GetID(), info)) {
1245+
if (provider.GetKeyOriginByXOnly(xkey, info)) {
12461246
return std::make_unique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider));
1247-
} else {
1248-
full_key[0] = 0x03;
1249-
pubkey = CPubKey(full_key);
1250-
if (provider.GetKeyOrigin(pubkey.GetID(), info)) {
1251-
return std::make_unique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider));
1252-
}
12531247
}
12541248
return key_provider;
12551249
}

src/script/sign.cpp

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -60,22 +60,7 @@ bool MutableTransactionSignatureCreator::CreateSchnorrSig(const SigningProvider&
6060
assert(sigversion == SigVersion::TAPROOT || sigversion == SigVersion::TAPSCRIPT);
6161

6262
CKey key;
63-
{
64-
// For now, use the old full pubkey-based key derivation logic. As it is indexed by
65-
// Hash160(full pubkey), we need to try both a version prefixed with 0x02, and one
66-
// with 0x03.
67-
unsigned char b[33] = {0x02};
68-
std::copy(pubkey.begin(), pubkey.end(), b + 1);
69-
CPubKey fullpubkey;
70-
fullpubkey.Set(b, b + 33);
71-
CKeyID keyid = fullpubkey.GetID();
72-
if (!provider.GetKey(keyid, key)) {
73-
b[0] = 0x03;
74-
fullpubkey.Set(b, b + 33);
75-
CKeyID keyid = fullpubkey.GetID();
76-
if (!provider.GetKey(keyid, key)) return false;
77-
}
78-
}
63+
if (!provider.GetKeyByXOnly(pubkey, key)) return false;
7964

8065
// BIP341/BIP342 signing needs lots of precomputed transaction data. While some
8166
// (non-SIGHASH_DEFAULT) sighash modes exist that can work with just some subset

src/script/signingprovider.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,30 @@ class SigningProvider
2626
virtual bool HaveKey(const CKeyID &address) const { return false; }
2727
virtual bool GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const { return false; }
2828
virtual bool GetTaprootSpendData(const XOnlyPubKey& output_key, TaprootSpendData& spenddata) const { return false; }
29+
30+
bool GetKeyByXOnly(const XOnlyPubKey& pubkey, CKey& key) const
31+
{
32+
for (const auto& id : pubkey.GetKeyIDs()) {
33+
if (GetKey(id, key)) return true;
34+
}
35+
return false;
36+
}
37+
38+
bool GetPubKeyByXOnly(const XOnlyPubKey& pubkey, CPubKey& out) const
39+
{
40+
for (const auto& id : pubkey.GetKeyIDs()) {
41+
if (GetPubKey(id, out)) return true;
42+
}
43+
return false;
44+
}
45+
46+
bool GetKeyOriginByXOnly(const XOnlyPubKey& pubkey, KeyOriginInfo& info) const
47+
{
48+
for (const auto& id : pubkey.GetKeyIDs()) {
49+
if (GetKeyOrigin(id, info)) return true;
50+
}
51+
return false;
52+
}
2953
};
3054

3155
extern const SigningProvider& DUMMY_SIGNING_PROVIDER;

0 commit comments

Comments
 (0)