Skip to content

Commit 4017d60

Browse files
committed
p2qrh: implements validateaddress RPC
1 parent 90811f4 commit 4017d60

7 files changed

Lines changed: 250 additions & 1 deletion

File tree

doc/design/p2qrh.md

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
*P2QRH Related Changes to Bitcoin Core*
2+
3+
4+
P2QRH functionality in Bitcoin Core spans several modules, including script execution, consensus rules, transaction validation, wallet support, and networking.
5+
6+
## 1. Script Execution and Opcodes (src/script/)
7+
8+
The scripting engine is central to P2QRH, as it will handle the validation of P2QRH outputs and execution.
9+
10+
11+
- **src/script/interpreter.cpp**:
12+
- `VerifyWitnessProgram`: Validates witness programs including P2QRH
13+
- `ExecuteWitnessScript`: Executes P2QRH script path spends
14+
- `ComputeTapleafHash`: Computes leaf hashes for Taproot scripts. Should leverage as is.
15+
- `ComputeTapbranchHash`: Computes branch hashes for Taproot Merkle trees. Should leverage as is.
16+
17+
**Key Functions:**
18+
- `CheckSchnorrSignature`: Validates Schnorr signatures for Taproot
19+
- `SignatureHashSchnorr`: Computes signature hashes for Taproot spends
20+
- `VerifyTaprootCommitment`: Validates Taproot output commitments
21+
22+
- **src/script/script.h**: Defines script opcodes and constants, including those modified or introduced for Tapscript (e.g., OP_CHECKSIGADD).
23+
- **src/script/signature_checker.h** and **src/script/signature_checker.cpp**: Implement signature verification logic, extended for Schnorr signatures (BIP-340) and Taproot-specific checks.
24+
25+
**Key Classes:**
26+
- `BaseSignatureChecker`: Abstract base class for signature verification, extended for Taproot.
27+
- `TransactionSignatureChecker`: Handles transaction-specific signature checks for P2QRH.
28+
29+
30+
## 2. Cryptographic Library (src/secp256k1/)
31+
32+
The following is specific to P2TR using Schnorr.
33+
The equivalent needs to be implemented for PQC algorithms implemented in [libbitcoinpqc](https://github.com/cryptoquick/libbitcoinpqc/tree/main).
34+
35+
36+
- **src/secp256k1/src/schnorr.c**: Implements Schnorr signature algorithms (signing and verification) per BIP-340.
37+
- **src/secp256k1/include/secp256k1_schnorr.h**: Defines the API for Schnorr signatures.
38+
- **src/secp256k1/src/modules/taproot/**:
39+
- `secp256k1_taproot_tweak_pubkey`: Tweaks public keys for Taproot
40+
- `secp256k1_taproot_tweak_seckey`: Tweaks private keys for Taproot
41+
- `secp256k1_taproot_leaf_hash`: Computes Taproot leaf hashes
42+
- `secp256k1_taproot_compute_merkle_root`: Computes Merkle roots
43+
44+
- **src/secp256k1/src/schnorr_impl.h**:
45+
- Implements core Schnorr signature algorithms
46+
- Provides batch verification functionality
47+
48+
49+
## 3. Consensus Rules (src/consensus/ and src/validation/)
50+
51+
52+
- **src/consensus/consensus.h**: Defines consensus parameters, including Taproot activation height.
53+
- **src/consensus/tx_verify.cpp**: Contains transaction verification logic.
54+
55+
**Key Functions:**
56+
- `CheckTransaction`: Ensures P2QRH transactions comply with consensus rules.
57+
58+
- **src/validation.cpp**: Handles block validation.
59+
60+
**Key Functions:**
61+
- `CheckBlock`: Validates blocks containing P2QRH transactions.
62+
- `ContextualCheckBlock`: Ensures Taproot activation rules are respected.
63+
64+
- **src/policy/policy.cpp**: Defines standardness rules for P2QRH transactions.
65+
66+
**Key Functions:**
67+
- `IsStandard`: Checks if P2QRH transactions are relayable by nodes.
68+
69+
- **src/validation.cpp**:
70+
- `CheckTaproot`: Validates Taproot consensus rules
71+
- `VerifyWitnessProgram`: Validates witness v1 programs
72+
- `CheckScriptFlags`: Enforces Taproot script validation flags
73+
74+
**Key Functions:**
75+
- `AcceptToMemoryPool`: Validates Taproot transaction acceptance
76+
- `CheckInputs`: Verifies Taproot input scripts
77+
78+
## 4. Wallet Support (src/wallet/)
79+
80+
81+
- **src/wallet/wallet.cpp**: Core wallet logic for Taproot
82+
- `SignTransaction`: Signs transactions including Taproot inputs
83+
- `FillPSBT`: Fills and signs PSBTs with Taproot data
84+
- `TransactionChangeType`: Handles Taproot change output creation
85+
86+
- **src/wallet/scriptpubkeyman.cpp**:
87+
- Manages Taproot output types via `DescriptorScriptPubKeyMan`
88+
- Handles Taproot address generation and key management
89+
90+
- **src/wallet/spend.cpp**:
91+
- `CreateTransaction`: Creates Taproot transactions
92+
- Implements coin selection for Taproot outputs
93+
94+
## 5. Address Encoding
95+
96+
97+
- **src/key_io.cpp**:
98+
- `EncodeBech32`: Implements Bech32m encoding for Taproot addresses
99+
- `DecodeBech32`: Parses Bech32m-encoded Taproot addresses
100+
- `GetDestinationForKey`: Creates Taproot destinations from keys
101+
102+
- **src/script/standard.cpp**:
103+
- `IsValidDestination`: Validates Taproot address formats
104+
- `GetScriptForDestination`: Creates scripts for Taproot addresses
105+
106+
- **src/core_io.cpp**:
107+
- Handles serialization of Taproot addresses and scripts
108+
- Implements Taproot address formatting
109+
110+
## 6. Networking and P2P
111+
112+
- **src/validation.cpp**:
113+
- `AcceptToMemoryPool`: Validates and accepts Taproot transactions
114+
- `PrecomputedTransactionData`: Handles Taproot signature verification data
115+
- `CheckTxInputs`: Validates Taproot input scripts
116+
117+
- **src/net_processing.cpp**:
118+
- `PeerManagerImpl::ProcessMessage`: Processes Taproot transactions
119+
- `BroadcastTransaction`: Relays Taproot transactions
120+
- `RelayTransaction`: Handles transaction relay policies
121+
122+
- **src/policy/policy.cpp**:
123+
- `IsStandardTx`: Enforces Taproot standardness rules
124+
- `IsWitnessStandard`: Validates Taproot witness structures
125+
126+
## 7. Descriptor Wallet Support
127+
128+
- **src/descriptor/descriptor.cpp**:
129+
- should implement `qrh()` and `rawqrh()` descriptors
130+
- Manages script and spending policies
131+
132+
- **src/wallet/scriptpubkeyman.cpp**:
133+
- `DescriptorScriptPubKeyMan`: Manages Taproot descriptors
134+
- Handles key generation and derivation
135+
- Implements address creation from descriptors
136+
137+
- **src/wallet/wallet.cpp**:
138+
- Integrates descriptor wallet support with Taproot
139+
- Manages descriptor-based wallet operations
140+
141+
## 8. p2qrh related rpc functions
142+
143+
| Functional Group | Method | Notes |
144+
|-----------------|---------|-------|
145+
| Descriptor Operations | deriveaddresses | Supports deriving addresses from qrh() descriptors for P2QRH outputs |
146+
| | getdescriptorinfo | Analyzes and validates tr() descriptors for P2QRH outputs |
147+
| | importdescriptors | Enables importing P2QRH descriptors into wallet |
148+
| | listdescriptors | Shows all descriptors including P2QRH tr() descriptors |
149+
| | createwalletdescriptor | Creates descriptor wallets supporting P2QRH functionality |
150+
| Address Operations | getnewaddress | Generates P2QRH addresses when address_type="bech32m" |
151+
| | getrawchangeaddress | Creates P2QRH change addresses with bech32m encoding |
152+
| | validateaddress | Validates P2QRH addresses (bc1p prefix) |
153+
| | getaddressinfo | Provides detailed information about P2QRH addresses |
154+
| PSBT Operations | walletprocesspsbt | Processes PSBTs containing P2QRH inputs/outputs |
155+
| | createpsbt | createpsbt '[]' '{"bc1r...":0.01}' |
156+
| | descriptorprocesspsbt | Handles PSBTs with P2QRH descriptor data |
157+
| | walletcreatefundedpsbt | Creates new PSBTs with P2QRH outputs |
158+
| | utxoupdatepsbt | Updates PSBT data for P2QRH inputs/outputs |
159+
| Raw Transaction Operations | signrawtransactionwithwallet | Signs P2QRH inputs using wallet keys |
160+
| | createrawtransaction| createrawtransaction '[]' '{"bc1r...":0.01}'
161+
| | signrawtransactionwithkey | Signs P2QRH inputs with specified keys |
162+
| | decoderawtransaction | Decodes transactions with P2QRH inputs/outputs |
163+
| | decodescript | decodescript "<pq2rh scriptPubKey>" |
164+
| Utxo | scantxoutset | scantxoutset start '["p2qrh(quantum_key)"] |
165+
| | gettxout | gettxout "txid" 0 |
166+
167+
168+
## 9. P2QRH Related Tests
169+
170+
### 9.1. Unit Tests
171+
172+
- **test/functional/feature_taproot.py**:
173+
- Tests Taproot activation sequence
174+
- Validates key-path and script-path spending
175+
- Tests commitment scheme verification
176+
- Checks address encoding/decoding
177+
178+
- **test/functional/wallet_taproot.py**:
179+
- Tests descriptor wallet integration
180+
- Verifies PSBT handling for Taproot
181+
- Tests change output creation
182+
- Validates address generation
183+
184+
- **src/test/script_tests.cpp**:
185+
- Unit tests for Tapscript execution
186+
- Tests Schnorr signature validation
187+
- Verifies leaf version handling
188+
- Tests script path validation
189+
190+
- **src/test/key_tests.cpp**:
191+
- Tests x-only pubkey operations
192+
- Validates key tweaking operations
193+
- Tests key aggregation
194+
195+
196+
### 9.2. Integration tests
197+
198+
1. Execute _validateaddress_ test (which includes P2PQRH related address tests)
199+
200+
```
201+
$ build/test/functional/rpc_validateaddress.py
202+
```

src/addresstype.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,11 @@ class CScriptVisitor
147147
{
148148
return CScript() << CScript::EncodeOP_N(id.GetWitnessVersion()) << id.GetWitnessProgram();
149149
}
150+
151+
CScript operator()(const WitnessV3P2QRH& id) const
152+
{
153+
return CScript() << CScript::EncodeOP_N(3) << ToByteVector(id);
154+
}
150155
};
151156

152157
class ValidDestinationVisitor
@@ -160,6 +165,7 @@ class ValidDestinationVisitor
160165
bool operator()(const WitnessV0ScriptHash& dest) const { return true; }
161166
bool operator()(const WitnessV1Taproot& dest) const { return true; }
162167
bool operator()(const WitnessUnknown& dest) const { return true; }
168+
bool operator()(const WitnessV3P2QRH& dest) const { return true; }
163169
};
164170
} // namespace
165171

src/addresstype.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,13 @@ struct WitnessV1Taproot : public XOnlyPubKey
9191
explicit WitnessV1Taproot(const XOnlyPubKey& xpk) : XOnlyPubKey(xpk) {}
9292
};
9393

94+
struct WitnessV3P2QRH : public BaseHash<uint256>
95+
{
96+
WitnessV3P2QRH() : BaseHash() {}
97+
explicit WitnessV3P2QRH(const uint256& hash) : BaseHash(hash) {}
98+
explicit WitnessV3P2QRH(const CScript& script);
99+
};
100+
94101
//! CTxDestination subtype to encode any future Witness version
95102
struct WitnessUnknown
96103
{
@@ -140,7 +147,7 @@ struct PayToAnchor : public WitnessUnknown
140147
* * WitnessUnknown: TxoutType::WITNESS_UNKNOWN destination (P2W??? address)
141148
* A CTxDestination is the internal data type encoded in a bitcoin address
142149
*/
143-
using CTxDestination = std::variant<CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, PayToAnchor, WitnessUnknown>;
150+
using CTxDestination = std::variant<CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, PayToAnchor, WitnessUnknown, WitnessV3P2QRH>;
144151

145152
/** Check whether a CTxDestination corresponds to one with an address. */
146153
bool IsValidDestination(const CTxDestination& dest);

src/key_io.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,14 @@ class DestinationEncoder
7777
return bech32::Encode(bech32::Encoding::BECH32M, m_params.Bech32HRP(), data);
7878
}
7979

80+
std::string operator()(const WitnessV3P2QRH& id) const
81+
{
82+
std::vector<unsigned char> data = {3}; // Version 3
83+
data.reserve(53); // Reserve space for the hash
84+
ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, id.begin(), id.end());
85+
return bech32::Encode(bech32::Encoding::BECH32M, m_params.Bech32HRP(), data);
86+
}
87+
8088
std::string operator()(const CNoDestination& no) const { return {}; }
8189
std::string operator()(const PubKeyDestination& pk) const { return {}; }
8290
};
@@ -181,6 +189,16 @@ CTxDestination DecodeDestination(const std::string& str, const CChainParams& par
181189
return tap;
182190
}
183191

192+
if (version == 3) {
193+
WitnessV3P2QRH qrh;
194+
if (data.size() == qrh.size()) {
195+
std::copy(data.begin(), data.end(), qrh.begin());
196+
return qrh;
197+
}
198+
error_str = strprintf("Invalid P2QRH address program size (%d %s)", data.size(), byte_str);
199+
return CNoDestination();
200+
}
201+
184202
if (CScript::IsPayToAnchor(version, data)) {
185203
return PayToAnchor();
186204
}

src/rpc/util.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,16 @@ class DescribeAddressVisitor
345345
obj.pushKV("witness_program", HexStr(id.GetWitnessProgram()));
346346
return obj;
347347
}
348+
349+
UniValue operator()(const WitnessV3P2QRH& id) const
350+
{
351+
UniValue obj(UniValue::VOBJ);
352+
obj.pushKV("isscript", true);
353+
obj.pushKV("iswitness", true);
354+
obj.pushKV("witness_version", 3);
355+
obj.pushKV("witness_program", HexStr(id));
356+
return obj;
357+
}
348358
};
349359

350360
UniValue DescribeAddress(const CTxDestination& dest)

src/wallet/rpc/addresses.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,7 @@ class DescribeWalletAddressVisitor
350350
UniValue operator()(const WitnessV1Taproot& id) const { return UniValue(UniValue::VOBJ); }
351351
UniValue operator()(const PayToAnchor& id) const { return UniValue(UniValue::VOBJ); }
352352
UniValue operator()(const WitnessUnknown& id) const { return UniValue(UniValue::VOBJ); }
353+
UniValue operator()(const WitnessV3P2QRH& id) const { return UniValue(UniValue::VOBJ); }
353354
};
354355

355356
static UniValue DescribeWalletAddress(const CWallet& wallet, const CTxDestination& dest)

test/functional/rpc_validateaddress.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,11 @@
171171
"bc1pfeessrawgf",
172172
"51024e73",
173173
),
174+
# P2QRH (Witness v3)
175+
(
176+
"bc1rc5jhzjnlf8pg4mdmhfuvqpvnr2quyd9j7mye5uly6psg9twghu4s0glfcg",
177+
"5320c525714a7f49c28aedbbba78c005931a81c234b2f6c99a73e4d06082adc8bf2b",
178+
),
174179
]
175180

176181

0 commit comments

Comments
 (0)