diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/key_io.cpp | 15 | ||||
-rw-r--r-- | src/rpc/util.cpp | 10 | ||||
-rw-r--r-- | src/script/descriptor.cpp | 1 | ||||
-rw-r--r-- | src/script/standard.cpp | 15 | ||||
-rw-r--r-- | src/script/standard.h | 13 | ||||
-rw-r--r-- | src/wallet/rpcwallet.cpp | 1 |
6 files changed, 45 insertions, 10 deletions
diff --git a/src/key_io.cpp b/src/key_io.cpp index dbcbfa1f29..615f4c9312 100644 --- a/src/key_io.cpp +++ b/src/key_io.cpp @@ -54,6 +54,14 @@ public: return bech32::Encode(bech32::Encoding::BECH32, m_params.Bech32HRP(), data); } + std::string operator()(const WitnessV1Taproot& tap) const + { + std::vector<unsigned char> data = {1}; + data.reserve(53); + ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, tap.begin(), tap.end()); + return bech32::Encode(bech32::Encoding::BECH32M, m_params.Bech32HRP(), data); + } + std::string operator()(const WitnessUnknown& id) const { if (id.version < 1 || id.version > 16 || id.length < 2 || id.length > 40) { @@ -135,6 +143,13 @@ CTxDestination DecodeDestination(const std::string& str, const CChainParams& par return CNoDestination(); } + if (version == 1 && data.size() == WITNESS_V1_TAPROOT_SIZE) { + static_assert(WITNESS_V1_TAPROOT_SIZE == WitnessV1Taproot::size()); + WitnessV1Taproot tap; + std::copy(data.begin(), data.end(), tap.begin()); + return tap; + } + if (version > 16) { error_str = "Invalid Bech32 address witness version"; return CNoDestination(); diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp index 7cf25e0c82..2059628b54 100644 --- a/src/rpc/util.cpp +++ b/src/rpc/util.cpp @@ -301,6 +301,16 @@ public: return obj; } + UniValue operator()(const WitnessV1Taproot& tap) const + { + UniValue obj(UniValue::VOBJ); + obj.pushKV("isscript", true); + obj.pushKV("iswitness", true); + obj.pushKV("witness_version", 1); + obj.pushKV("witness_program", HexStr(tap)); + return obj; + } + UniValue operator()(const WitnessUnknown& id) const { UniValue obj(UniValue::VOBJ); diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp index 19fad1009e..d4b43932b9 100644 --- a/src/script/descriptor.cpp +++ b/src/script/descriptor.cpp @@ -645,6 +645,7 @@ static std::optional<OutputType> OutputTypeFromDestination(const CTxDestination& } if (std::holds_alternative<WitnessV0KeyHash>(dest) || std::holds_alternative<WitnessV0ScriptHash>(dest) || + std::holds_alternative<WitnessV1Taproot>(dest) || std::holds_alternative<WitnessUnknown>(dest)) { return OutputType::BECH32; } diff --git a/src/script/standard.cpp b/src/script/standard.cpp index 540aa0f2d9..0a233b550a 100644 --- a/src/script/standard.cpp +++ b/src/script/standard.cpp @@ -242,13 +242,9 @@ bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet) return true; } case TxoutType::WITNESS_V1_TAPROOT: { - /* For now, no WitnessV1Taproot variant in CTxDestination exists, so map - * this to WitnessUnknown. */ - WitnessUnknown unk; - unk.version = 1; - std::copy(vSolutions[0].begin(), vSolutions[0].end(), unk.program); - unk.length = vSolutions[0].size(); - addressRet = unk; + WitnessV1Taproot tap; + std::copy(vSolutions[0].begin(), vSolutions[0].end(), tap.begin()); + addressRet = tap; return true; } case TxoutType::WITNESS_UNKNOWN: { @@ -337,6 +333,11 @@ public: return CScript() << OP_0 << ToByteVector(id); } + CScript operator()(const WitnessV1Taproot& tap) const + { + return CScript() << OP_1 << ToByteVector(tap); + } + CScript operator()(const WitnessUnknown& id) const { return CScript() << CScript::EncodeOP_N(id.version) << std::vector<unsigned char>(id.program, id.program + id.length); diff --git a/src/script/standard.h b/src/script/standard.h index 12ab9979a8..a96b096fa7 100644 --- a/src/script/standard.h +++ b/src/script/standard.h @@ -6,6 +6,7 @@ #ifndef BITCOIN_SCRIPT_STANDARD_H #define BITCOIN_SCRIPT_STANDARD_H +#include <pubkey.h> #include <script/interpreter.h> #include <uint256.h> #include <util/hash_type.h> @@ -113,6 +114,12 @@ struct WitnessV0KeyHash : public BaseHash<uint160> }; CKeyID ToKeyID(const WitnessV0KeyHash& key_hash); +struct WitnessV1Taproot : public XOnlyPubKey +{ + WitnessV1Taproot() : XOnlyPubKey() {} + explicit WitnessV1Taproot(const XOnlyPubKey& xpk) : XOnlyPubKey(xpk) {} +}; + //! CTxDestination subtype to encode any future Witness version struct WitnessUnknown { @@ -142,11 +149,11 @@ struct WitnessUnknown * * ScriptHash: TxoutType::SCRIPTHASH destination (P2SH) * * WitnessV0ScriptHash: TxoutType::WITNESS_V0_SCRIPTHASH destination (P2WSH) * * WitnessV0KeyHash: TxoutType::WITNESS_V0_KEYHASH destination (P2WPKH) - * * WitnessUnknown: TxoutType::WITNESS_UNKNOWN/WITNESS_V1_TAPROOT destination (P2W???) - * (taproot outputs do not require their own type as long as no wallet support exists) + * * WitnessV1Taproot: TxoutType::WITNESS_V1_TAPROOT destination (P2TR) + * * WitnessUnknown: TxoutType::WITNESS_UNKNOWN destination (P2W???) * A CTxDestination is the internal data type encoded in a bitcoin address */ -using CTxDestination = std::variant<CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessUnknown>; +using CTxDestination = std::variant<CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown>; /** Check whether a CTxDestination is a CNoDestination. */ bool IsValidDestination(const CTxDestination& dest); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 4e3c8ce49d..dd74d9f36b 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3737,6 +3737,7 @@ public: return obj; } + UniValue operator()(const WitnessV1Taproot& id) const { return UniValue(UniValue::VOBJ); } UniValue operator()(const WitnessUnknown& id) const { return UniValue(UniValue::VOBJ); } }; |