Skip to content

Commit 8dd0670

Browse files
committed
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.
1 parent 238d29a commit 8dd0670

File tree

8 files changed

+32
-42
lines changed

8 files changed

+32
-42
lines changed

src/addresstype.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,7 @@ bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
8787
return true;
8888
}
8989
case TxoutType::WITNESS_UNKNOWN: {
90-
WitnessUnknown unk;
91-
unk.version = vSolutions[0][0];
92-
std::copy(vSolutions[1].begin(), vSolutions[1].end(), unk.program);
93-
unk.length = vSolutions[1].size();
94-
addressRet = unk;
90+
addressRet = WitnessUnknown{vSolutions[0][0], vSolutions[1]};
9591
return true;
9692
}
9793
case TxoutType::MULTISIG:
@@ -138,7 +134,7 @@ class CScriptVisitor
138134

139135
CScript operator()(const WitnessUnknown& id) const
140136
{
141-
return CScript() << CScript::EncodeOP_N(id.version) << std::vector<unsigned char>(id.program, id.program + id.length);
137+
return CScript() << CScript::EncodeOP_N(id.GetWitnessVersion()) << id.GetWitnessProgram();
142138
}
143139
};
144140
} // namespace

src/addresstype.h

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -69,22 +69,26 @@ struct WitnessV1Taproot : public XOnlyPubKey
6969
//! CTxDestination subtype to encode any future Witness version
7070
struct WitnessUnknown
7171
{
72-
unsigned int version;
73-
unsigned int length;
74-
unsigned char program[40];
72+
private:
73+
unsigned int m_version;
74+
std::vector<unsigned char> m_program;
75+
76+
public:
77+
WitnessUnknown(unsigned int version, const std::vector<unsigned char>& program) : m_version(version), m_program(program) {}
78+
WitnessUnknown(int version, const std::vector<unsigned char>& program) : m_version(static_cast<unsigned int>(version)), m_program(program) {}
79+
80+
unsigned int GetWitnessVersion() const { return m_version; }
81+
const std::vector<unsigned char>& GetWitnessProgram() const LIFETIMEBOUND { return m_program; }
7582

7683
friend bool operator==(const WitnessUnknown& w1, const WitnessUnknown& w2) {
77-
if (w1.version != w2.version) return false;
78-
if (w1.length != w2.length) return false;
79-
return std::equal(w1.program, w1.program + w1.length, w2.program);
84+
if (w1.GetWitnessVersion() != w2.GetWitnessVersion()) return false;
85+
return w1.GetWitnessProgram() == w2.GetWitnessProgram();
8086
}
8187

8288
friend bool operator<(const WitnessUnknown& w1, const WitnessUnknown& w2) {
83-
if (w1.version < w2.version) return true;
84-
if (w1.version > w2.version) return false;
85-
if (w1.length < w2.length) return true;
86-
if (w1.length > w2.length) return false;
87-
return std::lexicographical_compare(w1.program, w1.program + w1.length, w2.program, w2.program + w2.length);
89+
if (w1.GetWitnessVersion() < w2.GetWitnessVersion()) return true;
90+
if (w1.GetWitnessVersion() > w2.GetWitnessVersion()) return false;
91+
return w1.GetWitnessProgram() < w2.GetWitnessProgram();
8892
}
8993
};
9094

src/key_io.cpp

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,13 @@ class DestinationEncoder
6666

6767
std::string operator()(const WitnessUnknown& id) const
6868
{
69-
if (id.version < 1 || id.version > 16 || id.length < 2 || id.length > 40) {
69+
const std::vector<unsigned char>& program = id.GetWitnessProgram();
70+
if (id.GetWitnessVersion() < 1 || id.GetWitnessVersion() > 16 || program.size() < 2 || program.size() > 40) {
7071
return {};
7172
}
72-
std::vector<unsigned char> data = {(unsigned char)id.version};
73-
data.reserve(1 + (id.length * 8 + 4) / 5);
74-
ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, id.program, id.program + id.length);
73+
std::vector<unsigned char> data = {(unsigned char)id.GetWitnessVersion()};
74+
data.reserve(1 + (program.size() * 8 + 4) / 5);
75+
ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, program.begin(), program.end());
7576
return bech32::Encode(bech32::Encoding::BECH32M, m_params.Bech32HRP(), data);
7677
}
7778

@@ -188,11 +189,7 @@ CTxDestination DecodeDestination(const std::string& str, const CChainParams& par
188189
return CNoDestination();
189190
}
190191

191-
WitnessUnknown unk;
192-
unk.version = version;
193-
std::copy(data.begin(), data.end(), unk.program);
194-
unk.length = data.size();
195-
return unk;
192+
return WitnessUnknown{version, data};
196193
} else {
197194
error_str = strprintf("Invalid padding in Bech32 data section");
198195
return CNoDestination();

src/rpc/util.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -303,8 +303,8 @@ class DescribeAddressVisitor
303303
{
304304
UniValue obj(UniValue::VOBJ);
305305
obj.pushKV("iswitness", true);
306-
obj.pushKV("witness_version", (int)id.version);
307-
obj.pushKV("witness_program", HexStr({id.program, id.length}));
306+
obj.pushKV("witness_version", id.GetWitnessVersion());
307+
obj.pushKV("witness_program", HexStr(id.GetWitnessProgram()));
308308
return obj;
309309
}
310310
};

src/test/fuzz/key.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ FUZZ_TARGET(key, .init = initialize_key)
186186
const CTxDestination tx_destination = GetDestinationForKey(pubkey, output_type);
187187
assert(output_type == OutputType::LEGACY);
188188
assert(IsValidDestination(tx_destination));
189-
assert(CTxDestination{PKHash{pubkey}} == tx_destination);
189+
assert(PKHash{pubkey} == *std::get_if<PKHash>(&tx_destination));
190190

191191
const CScript script_for_destination = GetScriptForDestination(tx_destination);
192192
assert(script_for_destination.size() == 25);

src/test/fuzz/util.cpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -188,15 +188,11 @@ CTxDestination ConsumeTxDestination(FuzzedDataProvider& fuzzed_data_provider) no
188188
tx_destination = WitnessV1Taproot{XOnlyPubKey{ConsumeUInt256(fuzzed_data_provider)}};
189189
},
190190
[&] {
191-
WitnessUnknown witness_unknown{};
192-
witness_unknown.version = fuzzed_data_provider.ConsumeIntegralInRange(2, 16);
193-
std::vector<uint8_t> witness_unknown_program_1{fuzzed_data_provider.ConsumeBytes<uint8_t>(40)};
194-
if (witness_unknown_program_1.size() < 2) {
195-
witness_unknown_program_1 = {0, 0};
191+
std::vector<unsigned char> program{ConsumeRandomLengthByteVector(fuzzed_data_provider, /*max_length=*/40)};
192+
if (program.size() < 2) {
193+
program = {0, 0};
196194
}
197-
witness_unknown.length = witness_unknown_program_1.size();
198-
std::copy(witness_unknown_program_1.begin(), witness_unknown_program_1.end(), witness_unknown.program);
199-
tx_destination = witness_unknown;
195+
tx_destination = WitnessUnknown{fuzzed_data_provider.ConsumeIntegralInRange<unsigned int>(2, 16), program};
200196
})};
201197
Assert(call_size == std::variant_size_v<CTxDestination>);
202198
return tx_destination;

src/test/script_standard_tests.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -249,10 +249,7 @@ BOOST_AUTO_TEST_CASE(script_standard_ExtractDestination)
249249
s.clear();
250250
s << OP_1 << ToByteVector(pubkey);
251251
BOOST_CHECK(ExtractDestination(s, address));
252-
WitnessUnknown unk;
253-
unk.length = 33;
254-
unk.version = 1;
255-
std::copy(pubkey.begin(), pubkey.end(), unk.program);
252+
WitnessUnknown unk{1, ToByteVector(pubkey)};
256253
BOOST_CHECK(std::get<WitnessUnknown>(address) == unk);
257254
}
258255

src/util/message.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ MessageVerificationResult MessageVerify(
4747
return MessageVerificationResult::ERR_PUBKEY_NOT_RECOVERED;
4848
}
4949

50-
if (!(CTxDestination(PKHash(pubkey)) == destination)) {
50+
if (!(PKHash(pubkey) == *std::get_if<PKHash>(&destination))) {
5151
return MessageVerificationResult::ERR_NOT_SIGNED;
5252
}
5353

0 commit comments

Comments
 (0)