aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Chow <github@achow101.com>2023-09-05 12:03:46 -0400
committerAndrew Chow <github@achow101.com>2023-09-12 12:14:31 -0400
commit8dd067088d41f021b357d7db5fa5f0a9f61edddc (patch)
tree6b2adb2b5c2e5cae92f032d910e7294d55d716a4
parent238d29aff9b43234e340a9cf17742b2be5d1e97d (diff)
downloadbitcoin-8dd067088d41f021b357d7db5fa5f0a9f61edddc.tar.xz
Make WitnessUnknown members private
Make sure that nothing else can change WitnessUnknown's data members by making them private. Also change the program to use a vector rather than C-style array.
-rw-r--r--src/addresstype.cpp8
-rw-r--r--src/addresstype.h26
-rw-r--r--src/key_io.cpp15
-rw-r--r--src/rpc/util.cpp4
-rw-r--r--src/test/fuzz/key.cpp2
-rw-r--r--src/test/fuzz/util.cpp12
-rw-r--r--src/test/script_standard_tests.cpp5
-rw-r--r--src/util/message.cpp2
8 files changed, 32 insertions, 42 deletions
diff --git a/src/addresstype.cpp b/src/addresstype.cpp
index 2454cfb5d9..349b50f0c9 100644
--- a/src/addresstype.cpp
+++ b/src/addresstype.cpp
@@ -87,11 +87,7 @@ bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
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;
+ addressRet = WitnessUnknown{vSolutions[0][0], vSolutions[1]};
return true;
}
case TxoutType::MULTISIG:
@@ -138,7 +134,7 @@ public:
CScript operator()(const WitnessUnknown& id) const
{
- return CScript() << CScript::EncodeOP_N(id.version) << std::vector<unsigned char>(id.program, id.program + id.length);
+ return CScript() << CScript::EncodeOP_N(id.GetWitnessVersion()) << id.GetWitnessProgram();
}
};
} // namespace
diff --git a/src/addresstype.h b/src/addresstype.h
index 6b651e9014..308840e6ae 100644
--- a/src/addresstype.h
+++ b/src/addresstype.h
@@ -69,22 +69,26 @@ struct WitnessV1Taproot : public XOnlyPubKey
//! CTxDestination subtype to encode any future Witness version
struct WitnessUnknown
{
- unsigned int version;
- unsigned int length;
- unsigned char program[40];
+private:
+ unsigned int m_version;
+ std::vector<unsigned char> m_program;
+
+public:
+ WitnessUnknown(unsigned int version, const std::vector<unsigned char>& program) : m_version(version), m_program(program) {}
+ WitnessUnknown(int version, const std::vector<unsigned char>& program) : m_version(static_cast<unsigned int>(version)), m_program(program) {}
+
+ unsigned int GetWitnessVersion() const { return m_version; }
+ const std::vector<unsigned char>& GetWitnessProgram() const LIFETIMEBOUND { return m_program; }
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);
+ if (w1.GetWitnessVersion() != w2.GetWitnessVersion()) return false;
+ return w1.GetWitnessProgram() == w2.GetWitnessProgram();
}
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);
+ if (w1.GetWitnessVersion() < w2.GetWitnessVersion()) return true;
+ if (w1.GetWitnessVersion() > w2.GetWitnessVersion()) return false;
+ return w1.GetWitnessProgram() < w2.GetWitnessProgram();
}
};
diff --git a/src/key_io.cpp b/src/key_io.cpp
index a061165613..96dc01550c 100644
--- a/src/key_io.cpp
+++ b/src/key_io.cpp
@@ -66,12 +66,13 @@ public:
std::string operator()(const WitnessUnknown& id) const
{
- if (id.version < 1 || id.version > 16 || id.length < 2 || id.length > 40) {
+ const std::vector<unsigned char>& program = id.GetWitnessProgram();
+ if (id.GetWitnessVersion() < 1 || id.GetWitnessVersion() > 16 || program.size() < 2 || program.size() > 40) {
return {};
}
- std::vector<unsigned char> data = {(unsigned char)id.version};
- data.reserve(1 + (id.length * 8 + 4) / 5);
- ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, id.program, id.program + id.length);
+ std::vector<unsigned char> data = {(unsigned char)id.GetWitnessVersion()};
+ data.reserve(1 + (program.size() * 8 + 4) / 5);
+ ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, program.begin(), program.end());
return bech32::Encode(bech32::Encoding::BECH32M, m_params.Bech32HRP(), data);
}
@@ -188,11 +189,7 @@ CTxDestination DecodeDestination(const std::string& str, const CChainParams& par
return CNoDestination();
}
- WitnessUnknown unk;
- unk.version = version;
- std::copy(data.begin(), data.end(), unk.program);
- unk.length = data.size();
- return unk;
+ return WitnessUnknown{version, data};
} else {
error_str = strprintf("Invalid padding in Bech32 data section");
return CNoDestination();
diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp
index 74ef04033e..e5ee6d7496 100644
--- a/src/rpc/util.cpp
+++ b/src/rpc/util.cpp
@@ -303,8 +303,8 @@ public:
{
UniValue obj(UniValue::VOBJ);
obj.pushKV("iswitness", true);
- obj.pushKV("witness_version", (int)id.version);
- obj.pushKV("witness_program", HexStr({id.program, id.length}));
+ obj.pushKV("witness_version", id.GetWitnessVersion());
+ obj.pushKV("witness_program", HexStr(id.GetWitnessProgram()));
return obj;
}
};
diff --git a/src/test/fuzz/key.cpp b/src/test/fuzz/key.cpp
index 60f4081432..be45443172 100644
--- a/src/test/fuzz/key.cpp
+++ b/src/test/fuzz/key.cpp
@@ -186,7 +186,7 @@ FUZZ_TARGET(key, .init = initialize_key)
const CTxDestination tx_destination = GetDestinationForKey(pubkey, output_type);
assert(output_type == OutputType::LEGACY);
assert(IsValidDestination(tx_destination));
- assert(CTxDestination{PKHash{pubkey}} == tx_destination);
+ assert(PKHash{pubkey} == *std::get_if<PKHash>(&tx_destination));
const CScript script_for_destination = GetScriptForDestination(tx_destination);
assert(script_for_destination.size() == 25);
diff --git a/src/test/fuzz/util.cpp b/src/test/fuzz/util.cpp
index ca2218e94c..201495a47e 100644
--- a/src/test/fuzz/util.cpp
+++ b/src/test/fuzz/util.cpp
@@ -188,15 +188,11 @@ CTxDestination ConsumeTxDestination(FuzzedDataProvider& fuzzed_data_provider) no
tx_destination = WitnessV1Taproot{XOnlyPubKey{ConsumeUInt256(fuzzed_data_provider)}};
},
[&] {
- WitnessUnknown witness_unknown{};
- witness_unknown.version = fuzzed_data_provider.ConsumeIntegralInRange(2, 16);
- std::vector<uint8_t> witness_unknown_program_1{fuzzed_data_provider.ConsumeBytes<uint8_t>(40)};
- if (witness_unknown_program_1.size() < 2) {
- witness_unknown_program_1 = {0, 0};
+ std::vector<unsigned char> program{ConsumeRandomLengthByteVector(fuzzed_data_provider, /*max_length=*/40)};
+ if (program.size() < 2) {
+ program = {0, 0};
}
- witness_unknown.length = witness_unknown_program_1.size();
- std::copy(witness_unknown_program_1.begin(), witness_unknown_program_1.end(), witness_unknown.program);
- tx_destination = witness_unknown;
+ tx_destination = WitnessUnknown{fuzzed_data_provider.ConsumeIntegralInRange<unsigned int>(2, 16), program};
})};
Assert(call_size == std::variant_size_v<CTxDestination>);
return tx_destination;
diff --git a/src/test/script_standard_tests.cpp b/src/test/script_standard_tests.cpp
index 1a205728d6..c3d5990e01 100644
--- a/src/test/script_standard_tests.cpp
+++ b/src/test/script_standard_tests.cpp
@@ -249,10 +249,7 @@ BOOST_AUTO_TEST_CASE(script_standard_ExtractDestination)
s.clear();
s << OP_1 << ToByteVector(pubkey);
BOOST_CHECK(ExtractDestination(s, address));
- WitnessUnknown unk;
- unk.length = 33;
- unk.version = 1;
- std::copy(pubkey.begin(), pubkey.end(), unk.program);
+ WitnessUnknown unk{1, ToByteVector(pubkey)};
BOOST_CHECK(std::get<WitnessUnknown>(address) == unk);
}
diff --git a/src/util/message.cpp b/src/util/message.cpp
index ec845aeffb..1afb28cc10 100644
--- a/src/util/message.cpp
+++ b/src/util/message.cpp
@@ -47,7 +47,7 @@ MessageVerificationResult MessageVerify(
return MessageVerificationResult::ERR_PUBKEY_NOT_RECOVERED;
}
- if (!(CTxDestination(PKHash(pubkey)) == destination)) {
+ if (!(PKHash(pubkey) == *std::get_if<PKHash>(&destination))) {
return MessageVerificationResult::ERR_NOT_SIGNED;
}