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 @@ class DestinationEncoder return bech32::Encode(bech32::Encoding::BECH32, m_params.Bech32HRP(), data); } + std::string operator()(const WitnessV1Taproot& tap) const + { + std::vector 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 @@ class DescribeAddressVisitor 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 OutputTypeFromDestination(const CTxDestination& } if (std::holds_alternative(dest) || std::holds_alternative(dest) || + std::holds_alternative(dest) || std::holds_alternative(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 @@ class CScriptVisitor 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(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 #include