Merge bitcoin/bitcoin#26567: Wallet: estimate the size of signed inputs using descriptors

10546a569c wallet: accurately account for the size of the witness stack (Antoine Poinsot)
9b7ec393b8 wallet: use descriptor satisfaction size to estimate inputs size (Antoine Poinsot)
8d870a9873 script/signingprovider: introduce a MultiSigningProvider (Antoine Poinsot)
fa7c46b503 descriptor: introduce a method to get the satisfaction size (Antoine Poinsot)
bdba7667d2 miniscript: introduce a helper to get the maximum witness size (Antoine Poinsot)
4ab382c2cd miniscript: make GetStackSize independent of P2WSH context (Antoine Poinsot)

Pull request description:

  The wallet currently estimates the size of a signed input by doing a dry run of the signing logic. This is unnecessary since all outputs we can sign for can be represented by a descriptor, and we can derive the size of a satisfaction ("signature") directly from the descriptor itself.
  In addition, the current approach does not generalize well: dry runs of the signing logic are only possible for the most basic scripts. See for instance the discussion in #24149 around that.

  This introduces a method to get the maximum size of a satisfaction from a descriptor, and makes the wallet use that instead of the dry-run.

ACKs for top commit:
  sipa:
    utACK 10546a569c
  achow101:
    re-ACK 10546a569c

Tree-SHA512: 43ed1529fbd30af709d903c8c5063235e8c6a03b500bc8f144273d6184e23a53edf0fea9ef898ed57d8a40d73208b5d935cc73b94a24fad3ad3c63b3b2027174
This commit is contained in:
Andrew Chow committed 2023-09-06 13:31:03 -04:00
commit d2ccca253f
15 files changed
+507 -206

No files matched your search

-51
View File
@@ -62,57 +62,6 @@ BOOST_FIXTURE_TEST_CASE(SubtractFee, TestChain100Setup)
BOOST_CHECK_EQUAL(fee, check_tx(fee + 123));
}
static void TestFillInputToWeight(int64_t additional_weight, std::vector<int64_t> expected_stack_sizes)
{
static const int64_t EMPTY_INPUT_WEIGHT = GetTransactionInputWeight(CTxIn());
CTxIn input;
int64_t target_weight = EMPTY_INPUT_WEIGHT + additional_weight;
BOOST_CHECK(FillInputToWeight(input, target_weight));
BOOST_CHECK_EQUAL(GetTransactionInputWeight(input), target_weight);
BOOST_CHECK_EQUAL(input.scriptWitness.stack.size(), expected_stack_sizes.size());
for (unsigned int i = 0; i < expected_stack_sizes.size(); ++i) {
BOOST_CHECK_EQUAL(input.scriptWitness.stack[i].size(), expected_stack_sizes[i]);
}
}
BOOST_FIXTURE_TEST_CASE(FillInputToWeightTest, BasicTestingSetup)
{
{
// Less than or equal minimum of 165 should not add any witness data
CTxIn input;
BOOST_CHECK(!FillInputToWeight(input, -1));
BOOST_CHECK_EQUAL(GetTransactionInputWeight(input), 165);
BOOST_CHECK_EQUAL(input.scriptWitness.stack.size(), 0);
BOOST_CHECK(!FillInputToWeight(input, 0));
BOOST_CHECK_EQUAL(GetTransactionInputWeight(input), 165);
BOOST_CHECK_EQUAL(input.scriptWitness.stack.size(), 0);
BOOST_CHECK(!FillInputToWeight(input, 164));
BOOST_CHECK_EQUAL(GetTransactionInputWeight(input), 165);
BOOST_CHECK_EQUAL(input.scriptWitness.stack.size(), 0);
BOOST_CHECK(FillInputToWeight(input, 165));
BOOST_CHECK_EQUAL(GetTransactionInputWeight(input), 165);
BOOST_CHECK_EQUAL(input.scriptWitness.stack.size(), 0);
}
// Make sure we can add at least one weight
TestFillInputToWeight(1, {0});
// 1 byte compact size uint boundary
TestFillInputToWeight(252, {251});
TestFillInputToWeight(253, {83, 168});
TestFillInputToWeight(262, {86, 174});
TestFillInputToWeight(263, {260});
// 3 byte compact size uint boundary
TestFillInputToWeight(65535, {65532});
TestFillInputToWeight(65536, {21842, 43688});
TestFillInputToWeight(65545, {21845, 43694});
TestFillInputToWeight(65546, {65541});
// Note: We don't test the next boundary because of memory allocation constraints.
}
BOOST_FIXTURE_TEST_CASE(wallet_duplicated_preset_inputs_test, TestChain100Setup)
{
// Verify that the wallet's Coin Selection process does not include pre-selected inputs twice in a transaction.
+3
View File
@@ -31,6 +31,9 @@ public:
bool Expand(int pos, const SigningProvider& provider, std::vector<CScript>& output_scripts, FlatSigningProvider& out, DescriptorCache* write_cache = nullptr) const override { return false; };
bool ExpandFromCache(int pos, const DescriptorCache& read_cache, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const override { return false; }
void ExpandPrivate(int pos, const SigningProvider& provider, FlatSigningProvider& out) const override {}
std::optional<int64_t> ScriptSize() const override { return {}; }
std::optional<int64_t> MaxSatisfactionWeight(bool) const override { return {}; }
std::optional<int64_t> MaxSatisfactionElems() const override { return {}; }
};
BOOST_FIXTURE_TEST_CASE(wallet_load_descriptors, TestingSetup)