Skip to content

Commit

Permalink
Merge bitcoin#28244: Break up script/standard.{h/cpp}
Browse files Browse the repository at this point in the history
91d924e Rename script/standard.{cpp/h} to script/solver.{cpp/h} (Andrew Chow)
bacdb2e Clean up script/standard.{h/cpp} includes (Andrew Chow)
f3c9078 Clean up things that include script/standard.h (Andrew Chow)
8bbe257 MOVEONLY: Move datacarrier defaults to policy.h (Andrew Chow)
7a172c7 Move CTxDestination to its own file (Andrew Chow)
145f36e Move Taproot{SpendData/Builder} to signingprovider.{h/cpp} (Andrew Chow)
86ea8be Move CScriptID to script.{h/cpp} (Andrew Chow)
b81ebff Remove ScriptHash from CScriptID constructor (Andrew Chow)
cba69dd Move MANDATORY_SCRIPT_VERIFY_FLAGS from script/standard.h to policy/policy.h (Anthony Towns)

Pull request description:

  Some future work needs to touch things in script/standard.{h/cpp}, however it is unclear if it is safe to do so as they are included in several different places that could effect standardness and consensus. It contains a mix of policy parameters, consensus parameters, and utilities only used by the wallet. This PR breaks up the various components and renames the files to clearly separate everything.

  * `CTxDestination` is moved to a new file `src/addresstype.{cpp/h}`
  * `TaprootSpendData` and `TaprootBuilder` (and their utility functions and structs) are moved to `SigningProvider` as these are used only during signing.
  * `CScriptID` is moved to `script/script.h` to be next to `CScript`.
  * `MANDATORY_SCRIPT_VERIFY_FLAGS` is moved to `interpreter.h`
  * The parameters `DEFAULT_ACCEPT_DATACARRIER` and `MAX_OP_RETURN_RELAY` are moved to `policy.h`
  * `standard.{cpp/h}` is renamed to `solver.{cpp/h}` since that's all that's left in the file after the above moves

ACKs for top commit:
  Sjors:
    ACK 91d924e
  ajtowns:
    ACK 91d924e
  MarcoFalke:
    ACK 91d924e 😇
  murchandamus:
    ACK 91d924e
  darosior:
    Code review ACK 91d924e.
  theStack:
    Code-review ACK 91d924e

Tree-SHA512: d347439890c652081f6a303d99b2bde6c371c96e7f4127c5db469764a17d39981f19884679ba883e28b733fde6142351dd8288c7bc61c379b7eefe7fa7acca1a
  • Loading branch information
fanquake committed Aug 17, 2023
2 parents d78ff38 + 91d924e commit 7ef2d4e
Show file tree
Hide file tree
Showing 83 changed files with 1,096 additions and 1,053 deletions.
8 changes: 5 additions & 3 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ endif
.PHONY: FORCE check-symbols check-security
# bitcoin core #
BITCOIN_CORE_H = \
addresstype.h \
addrdb.h \
addrman.h \
addrman_impl.h \
Expand Down Expand Up @@ -265,7 +266,7 @@ BITCOIN_CORE_H = \
script/sigcache.h \
script/sign.h \
script/signingprovider.h \
script/standard.h \
script/solver.h \
shutdown.h \
signet.h \
streams.h \
Expand Down Expand Up @@ -659,6 +660,7 @@ libbitcoin_consensus_a_SOURCES = \
libbitcoin_common_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BOOST_CPPFLAGS)
libbitcoin_common_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
libbitcoin_common_a_SOURCES = \
addresstype.cpp \
base58.cpp \
bech32.cpp \
chainparams.cpp \
Expand Down Expand Up @@ -699,7 +701,7 @@ libbitcoin_common_a_SOURCES = \
script/miniscript.cpp \
script/sign.cpp \
script/signingprovider.cpp \
script/standard.cpp \
script/solver.cpp \
warnings.cpp \
$(BITCOIN_CORE_H)

Expand Down Expand Up @@ -960,7 +962,7 @@ libbitcoinkernel_la_SOURCES = \
script/script.cpp \
script/script_error.cpp \
script/sigcache.cpp \
script/standard.cpp \
script/solver.cpp \
signet.cpp \
streams.cpp \
support/cleanse.cpp \
Expand Down
150 changes: 150 additions & 0 deletions src/addresstype.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
// Copyright (c) 2023 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or https://www.opensource.org/licenses/mit-license.php.

#include <addresstype.h>
#include <script/script.h>
#include <script/solver.h>
#include <hash.h>
#include <pubkey.h>
#include <uint256.h>
#include <util/hash_type.h>

#include <vector>

typedef std::vector<unsigned char> valtype;

ScriptHash::ScriptHash(const CScript& in) : BaseHash(Hash160(in)) {}
ScriptHash::ScriptHash(const CScriptID& in) : BaseHash(static_cast<uint160>(in)) {}

PKHash::PKHash(const CPubKey& pubkey) : BaseHash(pubkey.GetID()) {}
PKHash::PKHash(const CKeyID& pubkey_id) : BaseHash(pubkey_id) {}

WitnessV0KeyHash::WitnessV0KeyHash(const CPubKey& pubkey) : BaseHash(pubkey.GetID()) {}
WitnessV0KeyHash::WitnessV0KeyHash(const PKHash& pubkey_hash) : BaseHash(static_cast<uint160>(pubkey_hash)) {}

CKeyID ToKeyID(const PKHash& key_hash)
{
return CKeyID{static_cast<uint160>(key_hash)};
}

CKeyID ToKeyID(const WitnessV0KeyHash& key_hash)
{
return CKeyID{static_cast<uint160>(key_hash)};
}

CScriptID ToScriptID(const ScriptHash& script_hash)
{
return CScriptID{static_cast<uint160>(script_hash)};
}

WitnessV0ScriptHash::WitnessV0ScriptHash(const CScript& in)
{
CSHA256().Write(in.data(), in.size()).Finalize(begin());
}

bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
{
std::vector<valtype> vSolutions;
TxoutType whichType = Solver(scriptPubKey, vSolutions);

switch (whichType) {
case TxoutType::PUBKEY: {
CPubKey pubKey(vSolutions[0]);
if (!pubKey.IsValid())
return false;

addressRet = PKHash(pubKey);
return true;
}
case TxoutType::PUBKEYHASH: {
addressRet = PKHash(uint160(vSolutions[0]));
return true;
}
case TxoutType::SCRIPTHASH: {
addressRet = ScriptHash(uint160(vSolutions[0]));
return true;
}
case TxoutType::WITNESS_V0_KEYHASH: {
WitnessV0KeyHash hash;
std::copy(vSolutions[0].begin(), vSolutions[0].end(), hash.begin());
addressRet = hash;
return true;
}
case TxoutType::WITNESS_V0_SCRIPTHASH: {
WitnessV0ScriptHash hash;
std::copy(vSolutions[0].begin(), vSolutions[0].end(), hash.begin());
addressRet = hash;
return true;
}
case TxoutType::WITNESS_V1_TAPROOT: {
WitnessV1Taproot tap;
std::copy(vSolutions[0].begin(), vSolutions[0].end(), tap.begin());
addressRet = tap;
return true;
}
case TxoutType::WITNESS_UNKNOWN: {
WitnessUnknown unk;
unk.version = vSolutions[0][0];
std::copy(vSolutions[1].begin(), vSolutions[1].end(), unk.program);
unk.length = vSolutions[1].size();
addressRet = unk;
return true;
}
case TxoutType::MULTISIG:
case TxoutType::NULL_DATA:
case TxoutType::NONSTANDARD:
return false;
} // no default case, so the compiler can warn about missing cases
assert(false);
}

namespace {
class CScriptVisitor
{
public:
CScript operator()(const CNoDestination& dest) const
{
return CScript();
}

CScript operator()(const PKHash& keyID) const
{
return CScript() << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG;
}

CScript operator()(const ScriptHash& scriptID) const
{
return CScript() << OP_HASH160 << ToByteVector(scriptID) << OP_EQUAL;
}

CScript operator()(const WitnessV0KeyHash& id) const
{
return CScript() << OP_0 << ToByteVector(id);
}

CScript operator()(const WitnessV0ScriptHash& id) const
{
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);
}
};
} // namespace

CScript GetScriptForDestination(const CTxDestination& dest)
{
return std::visit(CScriptVisitor(), dest);
}

bool IsValidDestination(const CTxDestination& dest) {
return dest.index() != 0;
}
121 changes: 121 additions & 0 deletions src/addresstype.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
// Copyright (c) 2023 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or https://www.opensource.org/licenses/mit-license.php.

#ifndef BITCOIN_ADDRESSTYPE_H
#define BITCOIN_ADDRESSTYPE_H

#include <pubkey.h>
#include <script/script.h>
#include <uint256.h>
#include <util/hash_type.h>

#include <variant>
#include <algorithm>

class CNoDestination {
public:
friend bool operator==(const CNoDestination &a, const CNoDestination &b) { return true; }
friend bool operator<(const CNoDestination &a, const CNoDestination &b) { return true; }
};

struct PKHash : public BaseHash<uint160>
{
PKHash() : BaseHash() {}
explicit PKHash(const uint160& hash) : BaseHash(hash) {}
explicit PKHash(const CPubKey& pubkey);
explicit PKHash(const CKeyID& pubkey_id);
};
CKeyID ToKeyID(const PKHash& key_hash);

struct WitnessV0KeyHash;

struct ScriptHash : public BaseHash<uint160>
{
ScriptHash() : BaseHash() {}
// These don't do what you'd expect.
// Use ScriptHash(GetScriptForDestination(...)) instead.
explicit ScriptHash(const WitnessV0KeyHash& hash) = delete;
explicit ScriptHash(const PKHash& hash) = delete;

explicit ScriptHash(const uint160& hash) : BaseHash(hash) {}
explicit ScriptHash(const CScript& script);
explicit ScriptHash(const CScriptID& script);
};
CScriptID ToScriptID(const ScriptHash& script_hash);

struct WitnessV0ScriptHash : public BaseHash<uint256>
{
WitnessV0ScriptHash() : BaseHash() {}
explicit WitnessV0ScriptHash(const uint256& hash) : BaseHash(hash) {}
explicit WitnessV0ScriptHash(const CScript& script);
};

struct WitnessV0KeyHash : public BaseHash<uint160>
{
WitnessV0KeyHash() : BaseHash() {}
explicit WitnessV0KeyHash(const uint160& hash) : BaseHash(hash) {}
explicit WitnessV0KeyHash(const CPubKey& pubkey);
explicit WitnessV0KeyHash(const PKHash& pubkey_hash);
};
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
{
unsigned int version;
unsigned int length;
unsigned char program[40];

friend bool operator==(const WitnessUnknown& w1, const WitnessUnknown& w2) {
if (w1.version != w2.version) return false;
if (w1.length != w2.length) return false;
return std::equal(w1.program, w1.program + w1.length, w2.program);
}

friend bool operator<(const WitnessUnknown& w1, const WitnessUnknown& w2) {
if (w1.version < w2.version) return true;
if (w1.version > w2.version) return false;
if (w1.length < w2.length) return true;
if (w1.length > w2.length) return false;
return std::lexicographical_compare(w1.program, w1.program + w1.length, w2.program, w2.program + w2.length);
}
};

/**
* A txout script template with a specific destination. It is either:
* * CNoDestination: no destination set
* * PKHash: TxoutType::PUBKEYHASH destination (P2PKH)
* * ScriptHash: TxoutType::SCRIPTHASH destination (P2SH)
* * WitnessV0ScriptHash: TxoutType::WITNESS_V0_SCRIPTHASH destination (P2WSH)
* * WitnessV0KeyHash: TxoutType::WITNESS_V0_KEYHASH destination (P2WPKH)
* * 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, WitnessV1Taproot, WitnessUnknown>;

/** Check whether a CTxDestination is a CNoDestination. */
bool IsValidDestination(const CTxDestination& dest);

/**
* Parse a standard scriptPubKey for the destination address. Assigns result to
* the addressRet parameter and returns true if successful. Currently only works for P2PK,
* P2PKH, P2SH, P2WPKH, and P2WSH scripts.
*/
bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet);

/**
* Generate a Bitcoin scriptPubKey for the given CTxDestination. Returns a P2PKH
* script for a CKeyID destination, a P2SH script for a CScriptID, and an empty
* script for CNoDestination.
*/
CScript GetScriptForDestination(const CTxDestination& dest);

#endif // BITCOIN_ADDRESSTYPE_H
1 change: 0 additions & 1 deletion src/bench/descriptors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
#include <key.h>
#include <pubkey.h>
#include <script/descriptor.h>
#include <script/standard.h>

#include <string>
#include <utility>
Expand Down
2 changes: 1 addition & 1 deletion src/bench/verify_script.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#include <script/bitcoinconsensus.h>
#endif
#include <script/script.h>
#include <script/standard.h>
#include <script/interpreter.h>
#include <streams.h>
#include <test/util/transaction_utils.h>

Expand Down
2 changes: 1 addition & 1 deletion src/common/bloom.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#include <primitives/transaction.h>
#include <random.h>
#include <script/script.h>
#include <script/standard.h>
#include <script/solver.h>
#include <span.h>
#include <streams.h>
#include <util/fastrange.h>
Expand Down
2 changes: 1 addition & 1 deletion src/compressor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#include <compressor.h>

#include <pubkey.h>
#include <script/standard.h>
#include <script/script.h>

/*
* These check for scripts for which a special case with a shorter encoding is defined.
Expand Down
2 changes: 1 addition & 1 deletion src/core_write.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#include <key_io.h>
#include <script/descriptor.h>
#include <script/script.h>
#include <script/standard.h>
#include <script/solver.h>
#include <serialize.h>
#include <streams.h>
#include <undo.h>
Expand Down
1 change: 0 additions & 1 deletion src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@
#include <rpc/util.h>
#include <scheduler.h>
#include <script/sigcache.h>
#include <script/standard.h>
#include <shutdown.h>
#include <sync.h>
#include <timedata.h>
Expand Down
9 changes: 5 additions & 4 deletions src/interfaces/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
#ifndef BITCOIN_INTERFACES_WALLET_H
#define BITCOIN_INTERFACES_WALLET_H

#include <addresstype.h>
#include <consensus/amount.h>
#include <interfaces/chain.h> // For ChainClient
#include <pubkey.h> // For CKeyID and CScriptID (definitions needed in CTxDestination instantiation)
#include <script/standard.h> // For CTxDestination
#include <support/allocators/secure.h> // For SecureString
#include <interfaces/chain.h>
#include <pubkey.h>
#include <script/script.h>
#include <support/allocators/secure.h>
#include <util/fs.h>
#include <util/message.h>
#include <util/result.h>
Expand Down
1 change: 0 additions & 1 deletion src/kernel/mempool_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

#include <policy/feerate.h>
#include <policy/policy.h>
#include <script/standard.h>

#include <chrono>
#include <cstdint>
Expand Down
Loading

0 comments on commit 7ef2d4e

Please sign in to comment.