Skip to content

Add Taproot descriptors #20

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: taproot-rebase-52b9797
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/key_io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@ class DestinationEncoder : public boost::static_visitor<std::string>
return bech32::Encode(m_params.Bech32HRP(), data);
}

std::string operator()(const WitnessV1Point& id) const
{
std::vector<unsigned char> data = {1};
data.reserve(53);
ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, id.begin(), id.end());
return bech32::Encode(m_params.Bech32HRP(), data);
}

std::string operator()(const WitnessUnknown& id) const
{
if (id.version < 1 || id.version > 16 || id.length < 2 || id.length > 40) {
Expand Down
14 changes: 14 additions & 0 deletions src/pubkey.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,20 @@ bool CPubKey::CheckPayToContract(const CPubKey& base, const uint256& hash) const
return memcmp(out, vch, COMPRESSED_PUBLIC_KEY_SIZE) == 0;
}

bool CPubKey::CreatePayToContract(CPubKey& res, const uint256& hash) const
{
if (!IsCompressed()) return false;
secp256k1_pubkey base_point;
if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &base_point, vch, size())) return false;
if (!secp256k1_ec_pubkey_tweak_add(secp256k1_context_verify, &base_point, hash.begin())) return false;

size_t tweaked_len = COMPRESSED_PUBLIC_KEY_SIZE;
unsigned char tweaked[tweaked_len];
secp256k1_ec_pubkey_serialize(secp256k1_context_verify, tweaked, &tweaked_len, &base_point, SECP256K1_EC_COMPRESSED);
res.Set(tweaked, tweaked + tweaked_len);
return true;
}

/* static */ bool CPubKey::CheckLowS(const std::vector<unsigned char>& vchSig) {
secp256k1_ecdsa_signature sig;
if (!ecdsa_signature_parse_der_lax(secp256k1_context_verify, &sig, vchSig.data(), vchSig.size())) {
Expand Down
2 changes: 2 additions & 0 deletions src/pubkey.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ class CPubKey

//! Verify a P2C derivation. Hash must be a cryptographic hash that commits to base.
bool CheckPayToContract(const CPubKey& base, const uint256& hash) const;

bool CreatePayToContract(CPubKey& res, const uint256& hash) const;
};

struct CExtPubKey {
Expand Down
10 changes: 10 additions & 0 deletions src/rpc/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,16 @@ class DescribeAddressVisitor : public boost::static_visitor<UniValue>
return obj;
}

UniValue operator()(const WitnessV1Point& id) const
{
//TODO: What other data should be here?
UniValue obj(UniValue::VOBJ);
obj.pushKV("iswitness", true);
obj.pushKV("witness_version", 1);
obj.pushKV("witness_program", HexStr(id.begin(), id.end()));
return obj;
}

UniValue operator()(const WitnessUnknown& id) const
{
UniValue obj(UniValue::VOBJ);
Expand Down
110 changes: 110 additions & 0 deletions src/script/binarytree.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// Copyright (c) 2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.


#ifndef BITCOIN_BINARYTREE_H
#define BITCOIN_BINARYTREE_H


#include <script/script.h>
#include <util/memory.h>
#include <memory>


template <typename T>
class BinaryTree
{
protected:
BinaryTree* parent = nullptr;
std::unique_ptr<BinaryTree> left = nullptr;
std::unique_ptr<BinaryTree> right = nullptr;
std::unique_ptr<T> obj = nullptr;

public:
bool IsRoot() const { return parent == nullptr; }
bool IsLeaf() const { return obj != nullptr; }
bool IsNode() const { return !IsLeaf(); }
bool IsEmpty() const { return !left && !right && !IsLeaf(); }
bool IsFull() const { return (left && right) || IsLeaf(); }

const T* GetObj() const
{
if (!IsLeaf()) return nullptr;
return obj.get();
}

bool InsertLeaf(std::unique_ptr<T> sc)
{
if (!IsEmpty()) return false;
if (!sc) return false;
obj = std::move(sc);
return true;
}
bool InsertRight(BinaryTree child)
{
if (right) return false;
child.parent = this;
right = MakeUnique<BinaryTree>(std::move(child));
return true;
}
bool InsertLeft(BinaryTree child)
{
if (left) return false;
child.parent = this;
left = MakeUnique<BinaryTree>(std::move(child));
return true;
}
BinaryTree* GetInitLeftChild()
{
if (IsLeaf()) return nullptr;
if (!left) left = MakeUnique<BinaryTree>(this);
return left.get();
}
BinaryTree* GetInitRightChild()
{
if (!IsNode()) return nullptr;
if (!right) right = MakeUnique<BinaryTree>(BinaryTree(this));
return right.get();
}

BinaryTree* GetInitRightSibling()
{
if (!parent) return nullptr;
if (!parent->right) parent->right = MakeUnique<BinaryTree>(BinaryTree(parent));
if ((&*parent->right) == this) return nullptr;
return parent->right.get();
}
BinaryTree* GetInitLeftSibling()
{
if (!parent) return nullptr;
if (!parent->left) parent->left = MakeUnique<BinaryTree>(BinaryTree(parent));
return parent->left.get();
}

bool RemoveLeftChild()
{
if (!left) return false;
left.reset();
return true;
}

std::unique_ptr<T> ReplaceLeaf(std::unique_ptr<T> sc)
{
obj.swap(sc);
return sc;
}

BinaryTree* GetRawRightChild() const { return right.get(); }
BinaryTree* GetRawLeftChild() const { return left.get(); }
BinaryTree* GetParent() const { return parent; }

explicit BinaryTree() = default;
explicit BinaryTree(T sc) {obj = MakeUnique(std::move(sc));}
explicit BinaryTree(std::unique_ptr<T> sc) {obj = std::move(sc);}
explicit BinaryTree(BinaryTree* par) {parent = par;}

};


#endif
Loading