Merge 914c0cad97 into merged_master (Bitcoin PR bitcoin/bitcoin#22399)

This PR adds a fuzz test ensuring that all the different destination types
round-trip to strings (an important test given that Satoshi managed to mess
this up, having two different address types encode the same way..)

Anyway we fail this test, since both CNoDestination and NullData encode as
empty strings, and then this "decodes" as CNoDestination (and returns an
error, but the fuzztest doesn't check that). To make the fuzzer pass, I
changed NullData to encode and decode as "null".

I think this actually adds some functionality, letting you use "null" as
an "address" for sendtoaddress and createrawtransaction, thus burning the
coins and fixing #1011...but this was not my intent and we probably want
to think a bit more carefully before deliberately supporting this.
This commit is contained in:
Andrew Poelstra 2021-07-31 00:58:01 +00:00
commit e4746d6297
6 changed files with 69 additions and 77 deletions

View file

@ -2,6 +2,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <pubkey.h>
#include <test/fuzz/util.h>
#include <test/util/script.h>
#include <util/rbf.h>
@ -307,3 +308,44 @@ uint32_t ConsumeSequence(FuzzedDataProvider& fuzzed_data_provider) noexcept
}) :
fuzzed_data_provider.ConsumeIntegral<uint32_t>();
}
CTxDestination ConsumeTxDestination(FuzzedDataProvider& fuzzed_data_provider) noexcept
{
CTxDestination tx_destination;
const size_t call_size{CallOneOf(
fuzzed_data_provider,
[&] {
tx_destination = CNoDestination{};
},
[&] {
tx_destination = PKHash{ConsumeUInt160(fuzzed_data_provider)};
},
[&] {
tx_destination = ScriptHash{ConsumeUInt160(fuzzed_data_provider)};
},
[&] {
tx_destination = WitnessV0ScriptHash{ConsumeUInt256(fuzzed_data_provider)};
},
[&] {
tx_destination = WitnessV0KeyHash{ConsumeUInt160(fuzzed_data_provider)};
},
[&] {
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};
}
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 = NullData{};
})};
Assert(call_size == std::variant_size_v<CTxDestination>);
return tx_destination;
}