Skip to content

Commit 9853593

Browse files
authored
Merge pull request #83 from AnduroProject/AN-483-include-p2tsh-support
An 483 include p2tsh support
2 parents 9390b31 + 13b97a8 commit 9853593

21 files changed

+1647
-46
lines changed

doc/p2tsh.md

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# Coordinate BIP-360 Post-Quantum Wallet Guide
2+
3+
Guide for using Coordinate's BIP-360 post-quantum cryptographic wallets.
4+
5+
## Overview
6+
7+
BIP-360 adds quantum-resistant signatures to Coordinate with three signature schemes:
8+
9+
- **Hybrid**: Traditional + Quantum-resistant (Recommended)
10+
- **Schnorr**: Traditional signatures only
11+
- **SLHDSA**: Fully quantum-resistant
12+
13+
## Prerequisites
14+
15+
```conf
16+
# bitcoin.conf
17+
regtest=1
18+
rpcuser=marachain
19+
rpcpassword=marachain
20+
rpcport=18443
21+
```
22+
23+
## 1. Create Wallets
24+
25+
**Hybrid Wallet:**
26+
```bash
27+
./build/bin/bitcoin-cli -rpcuser=marachain -rpcpassword=marachain \
28+
-rpcport=18443 -regtest=1 \
29+
createwallet "test_p2tsh" false false "" false true false false true "hybrid"
30+
```
31+
32+
**Schnorr Wallet:**
33+
```bash
34+
./build/bin/bitcoin-cli -rpcuser=marachain -rpcpassword=marachain \
35+
-rpcport=18443 -regtest=1 \
36+
createwallet "schnorr_wallet" false false "" false true false false true "schnorr"
37+
```
38+
39+
**SLHDSA Wallet:**
40+
```bash
41+
./build/bin/bitcoin-cli -rpcuser=marachain -rpcpassword=marachain \
42+
-rpcport=18443 -regtest=1 \
43+
createwallet "slhdsa_wallet" false false "" false true false false true "slhdsa"
44+
```
45+
46+
## 2. Generate Addresses
47+
48+
**Hybrid Address:**
49+
```bash
50+
./build/bin/bitcoin-cli -rpcuser=marachain -rpcpassword=marachain \
51+
-rpcport=18443 -regtest=1 \
52+
-rpcwallet=test_p2tsh getnewaddress "" "p2tsh_hybrid"
53+
```
54+
55+
**Schnorr Address:**
56+
```bash
57+
./build/bin/bitcoin-cli -rpcuser=marachain -rpcpassword=marachain \
58+
-rpcport=18443 -regtest=1 \
59+
-rpcwallet=schnorr_wallet getnewaddress "" "p2tsh_schnorr"
60+
```
61+
62+
**SLHDSA Address:**
63+
```bash
64+
./build/bin/bitcoin-cli -rpcuser=marachain -rpcpassword=marachain \
65+
-rpcport=18443 -regtest=1 \
66+
-rpcwallet=slhdsa_wallet getnewaddress "" "p2tsh_slhdsa"
67+
```
68+
69+
## 3. Address Operations
70+
71+
**List Received Addresses:**
72+
```bash
73+
./build/bin/bitcoin-cli -rpcuser=marachain -rpcpassword=marachain \
74+
-rpcport=18443 -regtest=1 \
75+
-rpcwallet=test_p2tsh listreceivedbyaddress 0 true | jq -r '.[].address'
76+
```
77+
78+
**Get Address Info:**
79+
```bash
80+
./build/bin/bitcoin-cli -rpcuser=marachain -rpcpassword=marachain \
81+
-rpcport=18443 -regtest=1 \
82+
getaddressinfo ccrt1zgrunzrm9jg2uf9ge2ydrshap7v43z060tmh6sg2u4t4m83ugsa6sgrdv85
83+
```
84+
85+
**Validate Address:**
86+
```bash
87+
./build/bin/bitcoin-cli -rpcuser=marachain -rpcpassword=marachain \
88+
-rpcport=18443 -regtest=1 \
89+
validateaddress ccrt1zgrunzrm9jg2uf9ge2ydrshap7v43z060tmh6sg2u4t4m83ugsa6sgrdv85
90+
```
91+
92+
## 4. Mining & Transactions
93+
94+
**Generate Blocks:**
95+
```bash
96+
./build/bin/bitcoin-cli -rpcuser=marachain -rpcpassword=marachain \
97+
-rpcport=18443 -regtest=1 \
98+
generatetoaddress 1000 ccrt1zqrgy7n48gw5vhhdpfph3m2y6jgnl6auvwjcdvsvychx769zk0g5q2wy994
99+
```
100+
101+
**Send Transaction:**
102+
```bash
103+
./build/bin/bitcoin-cli -rpcuser=marachain -rpcpassword=marachain \
104+
-rpcport=18443 -regtest=1 \
105+
sendtoaddress ccrt1zwr6kkcwe2nqrt60rnpyzgs25wus3wynngjzl4sj6x6jq0cnm0q6sm434fg 0.1
106+
```

src/outputtype.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ std::optional<OutputType> ParseOutputType(const std::string& type)
3030
return OutputType::BECH32;
3131
} else if (type == OUTPUT_TYPE_STRING_BECH32M) {
3232
return OutputType::BECH32M;
33-
}
33+
}
3434
return std::nullopt;
3535
}
3636

src/outputtype.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ static constexpr auto OUTPUT_TYPES = std::array{
2727
OutputType::P2SH_SEGWIT,
2828
OutputType::BECH32,
2929
OutputType::BECH32M,
30+
3031
};
3132

3233
std::optional<OutputType> ParseOutputType(const std::string& str);

src/policy/policy.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,7 @@ bool AreCoordinateTransactionStandard(const CTransaction& tx, CCoinsViewCache& m
190190
if(tx.version == TRANSACTION_PEGIN_VERSION) {
191191
return true;
192192
}
193-
LogPrintf("transaction version is %i \n", tx.version);
194-
193+
195194
CAmount amountAssetInOut = CAmount(0);
196195
std::vector<unsigned char> currentAssetID = {};
197196
for (unsigned int i = 0; i < tx.vin.size(); i++) {

src/rpc/client.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
299299
{ "createwallet", 5, "descriptors"},
300300
{ "createwallet", 6, "load_on_startup"},
301301
{ "createwallet", 7, "external_signer"},
302+
{ "createwallet", 8, "enable_p2tsh"},
302303
{ "restorewallet", 2, "load_on_startup"},
303304
{ "loadwallet", 1, "load_on_startup"},
304305
{ "unloadwallet", 1, "load_on_startup"},

src/rpc/output_script.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ static RPCHelpMan validateaddress()
4343
{RPCResult::Type::BOOL, "iswitness", /*optional=*/true, "If the address is a witness address"},
4444
{RPCResult::Type::NUM, "witness_version", /*optional=*/true, "The version number of the witness program"},
4545
{RPCResult::Type::STR_HEX, "witness_program", /*optional=*/true, "The hex value of the witness program"},
46+
{RPCResult::Type::BOOL, "p2tsh", /*optional=*/true, "If the address is a P2TSH address (witness v2)"},
4647
{RPCResult::Type::STR, "error", /*optional=*/true, "Error message, if any"},
4748
{RPCResult::Type::ARR, "error_locations", /*optional=*/true, "Indices of likely error locations in address, if known (e.g. Bech32 errors)",
4849
{
@@ -73,6 +74,11 @@ static RPCHelpMan validateaddress()
7374

7475
UniValue detail = DescribeAddress(dest);
7576
ret.pushKVs(std::move(detail));
77+
78+
if (std::holds_alternative<WitnessV2P2TSH>(dest)) {
79+
ret.pushKV("p2tsh", true);
80+
}
81+
7682
} else {
7783
UniValue error_indices(UniValue::VARR);
7884
for (int i : error_locations) error_indices.push_back(i);

src/script/descriptor.cpp

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <optional>
2929
#include <string>
3030
#include <vector>
31+
#include <logging.h>
3132

3233
using util::Split;
3334

@@ -1631,7 +1632,7 @@ class TSHDescriptor final : public DescriptorImpl
16311632
uint256 merkle_root = builder.GetSpendData().merkle_root;
16321633

16331634
CScript output_script;
1634-
output_script << OP_3 << ToByteVector(merkle_root);
1635+
output_script << OP_2 << ToByteVector(merkle_root);
16351636

16361637
return {output_script};
16371638
}
@@ -2470,7 +2471,6 @@ std::vector<std::unique_ptr<DescriptorImpl>> ParseScript(uint32_t& key_exp_index
24702471
}
24712472
}
24722473
assert(TaprootBuilder::ValidDepths(depths));
2473-
24742474
// Make sure all vecs are of the same length, or exactly length 1
24752475
// For length 1 vectors, clone subdescs until vector is the same length
24762476
for (auto& vec : subscripts) {
@@ -2483,7 +2483,6 @@ std::vector<std::unique_ptr<DescriptorImpl>> ParseScript(uint32_t& key_exp_index
24832483
return {};
24842484
}
24852485
}
2486-
24872486
if (internal_keys.size() > 1 && internal_keys.size() != max_providers_len) {
24882487
error = strprintf("tr(): Multipath internal key mismatches multipath subscripts lengths");
24892488
return {};
@@ -2492,7 +2491,6 @@ std::vector<std::unique_ptr<DescriptorImpl>> ParseScript(uint32_t& key_exp_index
24922491
while (internal_keys.size() < max_providers_len) {
24932492
internal_keys.emplace_back(internal_keys.at(0)->Clone());
24942493
}
2495-
24962494
// Build the final descriptors vector
24972495
for (size_t i = 0; i < max_providers_len; ++i) {
24982496
// Build final subscripts vectors by retrieving the i'th subscript for each vector in subscripts
@@ -2515,7 +2513,6 @@ std::vector<std::unique_ptr<DescriptorImpl>> ParseScript(uint32_t& key_exp_index
25152513
// P2TSH only supports script path, no internal key
25162514
std::vector<std::vector<std::unique_ptr<DescriptorImpl>>> subscripts;
25172515
std::vector<int> depths;
2518-
25192516
if (expr.size()) {
25202517
/** The path from the top of the tree to what we're currently processing.
25212518
* branches[i] == false: left branch in the i'th step from the top; true: right branch.
@@ -2534,7 +2531,9 @@ std::vector<std::unique_ptr<DescriptorImpl>> ParseScript(uint32_t& key_exp_index
25342531
// Process the actual script expression.
25352532
auto sarg = Expr(expr);
25362533
subscripts.emplace_back(ParseScript(key_exp_index, sarg, ParseScriptContext::P2TSH, out, error));
2537-
if (subscripts.back().empty()) return {};
2534+
if (subscripts.back().empty()) {
2535+
return {};
2536+
}
25382537
depths.push_back(branches.size());
25392538
// Process closing braces; one is expected for every right branch we were in.
25402539
while (branches.size() && branches.back()) {
@@ -2559,7 +2558,6 @@ std::vector<std::unique_ptr<DescriptorImpl>> ParseScript(uint32_t& key_exp_index
25592558
return {};
25602559
}
25612560
}
2562-
25632561
assert(TaprootBuilder::ValidDepths(depths));
25642562

25652563
// Build the final descriptors vector

0 commit comments

Comments
 (0)