policy: ephemeral dust followups #31279

pull instagibbs wants to merge 29 commits into bitcoin:master from instagibbs:2024-11-eph_dust_followups changing 15 files +210 −146
  1. DrahtBot commented at 6:38 pm on November 12, 2024: contributor

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    Code Coverage & Benchmarks

    For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/31279.

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    ACK naumenkogs, hodlinator, theStack, glozow

    If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

  2. DrahtBot added the label TX fees and policy on Nov 12, 2024
  3. glozow added this to the milestone 29.0 on Nov 13, 2024
  4. glozow commented at 1:07 am on November 13, 2024: member
    Time to sweep the ephemeral top 9 commits
  5. CheckEphemeralSpends: only compute txid of tx when needed cbf1a47d60
  6. instagibbs force-pushed on Nov 13, 2024
  7. instagibbs marked this as ready for review on Nov 13, 2024
  8. instagibbs commented at 4:29 pm on November 13, 2024: member
    ready for review, I think
  9. marcofleon commented at 6:06 pm on November 13, 2024: contributor

    From various fuzz runs:

     0UndefinedBehaviorSanitizer:DEADLYSIGNAL
     1==1654160==ERROR: UndefinedBehaviorSanitizer: SEGV on unknown address 0x000000000010 (pc 0x7f4ed8ac0563 bp 0x7ffd7bdeff90 sp 0x7ffd7bdefba8 T1654160)
     2==1654160==The signal is caused by a READ memory access.
     3==1654160==Hint: address points to the zero page.
     4    [#0](/bitcoin-bitcoin/0/) 0x7f4ed8ac0563 in std::_Rb_tree_rebalance_for_erase(std::_Rb_tree_node_base*, std::_Rb_tree_node_base&) (/lib/x86_64-linux-gnu/libstdc++.so.6+0xc0563) (BuildId: 0c47cec75226c7736517d5acb61e373d541a5023)
     5    [#1](/bitcoin-bitcoin/1/) 0x5579575141b5 in std::_Rb_tree<COutPoint, COutPoint, std::_Identity<COutPoint>, std::less<COutPoint>, std::allocator<COutPoint>>::_M_erase_aux(std::_Rb_tree_const_iterator<COutPoint>) /usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/bits/stl_tree.h:2492:26
     6    [#2](/bitcoin-bitcoin/2/) 0x5579575141b5 in std::_Rb_tree<COutPoint, COutPoint, std::_Identity<COutPoint>, std::less<COutPoint>, std::allocator<COutPoint>>::erase[abi:cxx11](std::_Rb_tree_const_iterator<COutPoint>) /usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/bits/stl_tree.h:1197:2
     7    [#3](/bitcoin-bitcoin/3/) 0x5579575141b5 in std::set<COutPoint, std::less<COutPoint>, std::allocator<COutPoint>>::erase[abi:cxx11](std::_Rb_tree_const_iterator<COutPoint>) /usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/bits/stl_set.h:655:21
     8    [#4](/bitcoin-bitcoin/4/) 0x5579575141b5 in (anonymous namespace)::ephemeral_package_eval_fuzz_target(std::span<unsigned char const, 18446744073709551615ul>)::$_0::operator()() const /root/bitcoin/ephemeralfuzzbuild/src/test/fuzz/../../../../src/test/fuzz/package_eval.cpp:257:35
     9    [#5](/bitcoin-bitcoin/5/) 0x5579575141b5 in (anonymous namespace)::ephemeral_package_eval_fuzz_target(std::span<unsigned char const, 18446744073709551615ul>) /root/bitcoin/ephemeralfuzzbuild/src/test/fuzz/../../../../src/test/fuzz/package_eval.cpp:228:27
    10    [#6](/bitcoin-bitcoin/6/) 0x5579576628c7 in std::function<void (std::span<unsigned char const, 18446744073709551615ul>)>::operator()(std::span<unsigned char const, 18446744073709551615ul>) const /usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/bits/std_function.h:591:9
    11    [#7](/bitcoin-bitcoin/7/) 0x5579576628c7 in LLVMFuzzerTestOneInput /root/bitcoin/ephemeralfuzzbuild/src/test/fuzz/util/../../../../../src/test/fuzz/fuzz.cpp:213:5
    12    [#8](/bitcoin-bitcoin/8/) 0x5579572dfd00 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/root/bitcoin/ephemeralfuzzbuild/src/test/fuzz/fuzz+0x94ed00) (BuildId: a5b9aaf3b4abf14131d79477c841f1529fb62bf2)
    13    [#9](/bitcoin-bitcoin/9/) 0x5579572df435 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) (/root/bitcoin/ephemeralfuzzbuild/src/test/fuzz/fuzz+0x94e435) (BuildId: a5b9aaf3b4abf14131d79477c841f1529fb62bf2)
    14    [#10](/bitcoin-bitcoin/10/) 0x5579572e0bc5 in fuzzer::Fuzzer::MutateAndTestOne() (/root/bitcoin/ephemeralfuzzbuild/src/test/fuzz/fuzz+0x94fbc5) (BuildId: a5b9aaf3b4abf14131d79477c841f1529fb62bf2)
    15    [#11](/bitcoin-bitcoin/11/) 0x5579572e17c5 in fuzzer::Fuzzer::Loop(std::vector<fuzzer::SizedFile, std::allocator<fuzzer::SizedFile>>&) (/root/bitcoin/ephemeralfuzzbuild/src/test/fuzz/fuzz+0x9507c5) (BuildId: a5b9aaf3b4abf14131d79477c841f1529fb62bf2)
    16    [#12](/bitcoin-bitcoin/12/) 0x5579572cf9ef in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/root/bitcoin/ephemeralfuzzbuild/src/test/fuzz/fuzz+0x93e9ef) (BuildId: a5b9aaf3b4abf14131d79477c841f1529fb62bf2)
    17    [#13](/bitcoin-bitcoin/13/) 0x5579572f8da2 in main (/root/bitcoin/ephemeralfuzzbuild/src/test/fuzz/fuzz+0x967da2) (BuildId: a5b9aaf3b4abf14131d79477c841f1529fb62bf2)
    18    [#14](/bitcoin-bitcoin/14/) 0x7f4ed8608249  (/lib/x86_64-linux-gnu/libc.so.6+0x27249) (BuildId: 58254ca972028402bc40624f81388d85ec95f70d)
    19    [#15](/bitcoin-bitcoin/15/) 0x7f4ed8608304 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x27304) (BuildId: 58254ca972028402bc40624f81388d85ec95f70d)
    20    [#16](/bitcoin-bitcoin/16/) 0x5579572c4de0 in _start (/root/bitcoin/ephemeralfuzzbuild/src/test/fuzz/fuzz+0x933de0) (BuildId: a5b9aaf3b4abf14131d79477c841f1529fb62bf2)
    
     0../../../../src/test/fuzz/package_eval.cpp:286 operator(): Assertion `outpoints.insert(in.prevout).second' failed.
     1==1656011== ERROR: libFuzzer: deadly signal
     2    [#0](/bitcoin-bitcoin/0/) 0x55a766a785a4 in __sanitizer_print_stack_trace (/root/bitcoin/ephemeralfuzzbuild/src/test/fuzz/fuzz+0x9915a4) (BuildId: a5b9aaf3b4abf14131d79477c841f1529fb62bf2)
     3    [#1](/bitcoin-bitcoin/1/) 0x55a766a4e4d8 in fuzzer::PrintStackTrace() (/root/bitcoin/ephemeralfuzzbuild/src/test/fuzz/fuzz+0x9674d8) (BuildId: a5b9aaf3b4abf14131d79477c841f1529fb62bf2)
     4    [#2](/bitcoin-bitcoin/2/) 0x55a766a348f3 in fuzzer::Fuzzer::CrashCallback() (/root/bitcoin/ephemeralfuzzbuild/src/test/fuzz/fuzz+0x94d8f3) (BuildId: a5b9aaf3b4abf14131d79477c841f1529fb62bf2)
     5    [#3](/bitcoin-bitcoin/3/) 0x7f5f78a1d04f  (/lib/x86_64-linux-gnu/libc.so.6+0x3c04f) (BuildId: 58254ca972028402bc40624f81388d85ec95f70d)
     6    [#4](/bitcoin-bitcoin/4/) 0x7f5f78a6be2b  (/lib/x86_64-linux-gnu/libc.so.6+0x8ae2b) (BuildId: 58254ca972028402bc40624f81388d85ec95f70d)
     7    [#5](/bitcoin-bitcoin/5/) 0x7f5f78a1cfb1 in raise (/lib/x86_64-linux-gnu/libc.so.6+0x3bfb1) (BuildId: 58254ca972028402bc40624f81388d85ec95f70d)
     8    [#6](/bitcoin-bitcoin/6/) 0x7f5f78a07471 in abort (/lib/x86_64-linux-gnu/libc.so.6+0x26471) (BuildId: 58254ca972028402bc40624f81388d85ec95f70d)
     9    [#7](/bitcoin-bitcoin/7/) 0x55a766f77e07 in assertion_fail(std::basic_string_view<char, std::char_traits<char>>, int, std::basic_string_view<char, std::char_traits<char>>, std::basic_string_view<char, std::char_traits<char>>) /root/bitcoin/ephemeralfuzzbuild/src/util/../../../src/util/check.cpp:34:5
    10    [#8](/bitcoin-bitcoin/8/) 0x55a766c6ac7f in bool&& inline_assertion_check<true, bool>(bool&&, char const*, int, char const*, char const*) /root/bitcoin/ephemeralfuzzbuild/src/test/fuzz/../../../../src/util/check.h:59:13
    11    [#9](/bitcoin-bitcoin/9/) 0x55a766c6ac7f in (anonymous namespace)::ephemeral_package_eval_fuzz_target(std::span<unsigned char const, 18446744073709551615ul>)::$_0::operator()() const /root/bitcoin/ephemeralfuzzbuild/src/test/fuzz/../../../../src/test/fuzz/package_eval.cpp:286:25
    12    [#10](/bitcoin-bitcoin/10/) 0x55a766c6ac7f in (anonymous namespace)::ephemeral_package_eval_fuzz_target(std::span<unsigned char const, 18446744073709551615ul>) /root/bitcoin/ephemeralfuzzbuild/src/test/fuzz/../../../../src/test/fuzz/package_eval.cpp:228:27
    13    [#11](/bitcoin-bitcoin/11/) 0x55a766db88c7 in std::function<void (std::span<unsigned char const, 18446744073709551615ul>)>::operator()(std::span<unsigned char const, 18446744073709551615ul>) const /usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/bits/std_function.h:591:9
    14    [#12](/bitcoin-bitcoin/12/) 0x55a766db88c7 in LLVMFuzzerTestOneInput /root/bitcoin/ephemeralfuzzbuild/src/test/fuzz/util/../../../../../src/test/fuzz/fuzz.cpp:213:5
    15    [#13](/bitcoin-bitcoin/13/) 0x55a766a35d00 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/root/bitcoin/ephemeralfuzzbuild/src/test/fuzz/fuzz+0x94ed00) (BuildId: a5b9aaf3b4abf14131d79477c841f1529fb62bf2)
    16    [#14](/bitcoin-bitcoin/14/) 0x55a766a35435 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) (/root/bitcoin/ephemeralfuzzbuild/src/test/fuzz/fuzz+0x94e435) (BuildId: a5b9aaf3b4abf14131d79477c841f1529fb62bf2)
    17    [#15](/bitcoin-bitcoin/15/) 0x55a766a36bc5 in fuzzer::Fuzzer::MutateAndTestOne() (/root/bitcoin/ephemeralfuzzbuild/src/test/fuzz/fuzz+0x94fbc5) (BuildId: a5b9aaf3b4abf14131d79477c841f1529fb62bf2)
    18    [#16](/bitcoin-bitcoin/16/) 0x55a766a377c5 in fuzzer::Fuzzer::Loop(std::vector<fuzzer::SizedFile, std::allocator<fuzzer::SizedFile>>&) (/root/bitcoin/ephemeralfuzzbuild/src/test/fuzz/fuzz+0x9507c5) (BuildId: a5b9aaf3b4abf14131d79477c841f1529fb62bf2)
    19    [#17](/bitcoin-bitcoin/17/) 0x55a766a259ef in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/root/bitcoin/ephemeralfuzzbuild/src/test/fuzz/fuzz+0x93e9ef) (BuildId: a5b9aaf3b4abf14131d79477c841f1529fb62bf2)
    20    [#18](/bitcoin-bitcoin/18/) 0x55a766a4eda2 in main (/root/bitcoin/ephemeralfuzzbuild/src/test/fuzz/fuzz+0x967da2) (BuildId: a5b9aaf3b4abf14131d79477c841f1529fb62bf2)
    21    [#19](/bitcoin-bitcoin/19/) 0x7f5f78a08249  (/lib/x86_64-linux-gnu/libc.so.6+0x27249) (BuildId: 58254ca972028402bc40624f81388d85ec95f70d)
    22    [#20](/bitcoin-bitcoin/20/) 0x7f5f78a08304 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x27304) (BuildId: 58254ca972028402bc40624f81388d85ec95f70d)
    23    [#21](/bitcoin-bitcoin/21/) 0x55a766a1ade0 in _start (/root/bitcoin/ephemeralfuzzbuild/src/test/fuzz/fuzz+0x933de0) (BuildId: a5b9aaf3b4abf14131d79477c841f1529fb62bf2)
    
     0terminate called after throwing an instance of 'std::out_of_range'
     1  what():  map::at
     2==1656362== ERROR: libFuzzer: deadly signal
     3    [#0](/bitcoin-bitcoin/0/) 0x5560e2e3c5a4 in __sanitizer_print_stack_trace (/root/bitcoin/ephemeralfuzzbuild/src/test/fuzz/fuzz+0x9915a4) (BuildId: a5b9aaf3b4abf14131d79477c841f1529fb62bf2)
     4    [#1](/bitcoin-bitcoin/1/) 0x5560e2e124d8 in fuzzer::PrintStackTrace() (/root/bitcoin/ephemeralfuzzbuild/src/test/fuzz/fuzz+0x9674d8) (BuildId: a5b9aaf3b4abf14131d79477c841f1529fb62bf2)
     5    [#2](/bitcoin-bitcoin/2/) 0x5560e2df88f3 in fuzzer::Fuzzer::CrashCallback() (/root/bitcoin/ephemeralfuzzbuild/src/test/fuzz/fuzz+0x94d8f3) (BuildId: a5b9aaf3b4abf14131d79477c841f1529fb62bf2)
     6    [#3](/bitcoin-bitcoin/3/) 0x7fc27ba1d04f  (/lib/x86_64-linux-gnu/libc.so.6+0x3c04f) (BuildId: 58254ca972028402bc40624f81388d85ec95f70d)
     7    [#4](/bitcoin-bitcoin/4/) 0x7fc27ba6be2b  (/lib/x86_64-linux-gnu/libc.so.6+0x8ae2b) (BuildId: 58254ca972028402bc40624f81388d85ec95f70d)
     8    [#5](/bitcoin-bitcoin/5/) 0x7fc27ba1cfb1 in raise (/lib/x86_64-linux-gnu/libc.so.6+0x3bfb1) (BuildId: 58254ca972028402bc40624f81388d85ec95f70d)
     9    [#6](/bitcoin-bitcoin/6/) 0x7fc27ba07471 in abort (/lib/x86_64-linux-gnu/libc.so.6+0x26471) (BuildId: 58254ca972028402bc40624f81388d85ec95f70d)
    10    [#7](/bitcoin-bitcoin/7/) 0x7fc27be9d918  (/lib/x86_64-linux-gnu/libstdc++.so.6+0x9d918) (BuildId: 0c47cec75226c7736517d5acb61e373d541a5023)
    11    [#8](/bitcoin-bitcoin/8/) 0x7fc27bea8e19  (/lib/x86_64-linux-gnu/libstdc++.so.6+0xa8e19) (BuildId: 0c47cec75226c7736517d5acb61e373d541a5023)
    12    [#9](/bitcoin-bitcoin/9/) 0x7fc27bea8e84 in std::terminate() (/lib/x86_64-linux-gnu/libstdc++.so.6+0xa8e84) (BuildId: 0c47cec75226c7736517d5acb61e373d541a5023)
    13    [#10](/bitcoin-bitcoin/10/) 0x7fc27bea90d7 in __cxa_throw (/lib/x86_64-linux-gnu/libstdc++.so.6+0xa90d7) (BuildId: 0c47cec75226c7736517d5acb61e373d541a5023)
    14    [#11](/bitcoin-bitcoin/11/) 0x7fc27bea023f in std::__throw_out_of_range(char const*) (/lib/x86_64-linux-gnu/libstdc++.so.6+0xa023f) (BuildId: 0c47cec75226c7736517d5acb61e373d541a5023)
    15    [#12](/bitcoin-bitcoin/12/) 0x5560e30339be in std::map<COutPoint, long, std::less<COutPoint>, std::allocator<std::pair<COutPoint const, long>>>::at(COutPoint const&) /usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/bits/stl_map.h:551:4
    16    [#13](/bitcoin-bitcoin/13/) 0x5560e302e1d4 in (anonymous namespace)::ephemeral_package_eval_fuzz_target(std::span<unsigned char const, 18446744073709551615ul>)::$_0::operator()() const /root/bitcoin/ephemeralfuzzbuild/src/test/fuzz/../../../../src/test/fuzz/package_eval.cpp:260:50
    17    [#14](/bitcoin-bitcoin/14/) 0x5560e302e1d4 in (anonymous namespace)::ephemeral_package_eval_fuzz_target(std::span<unsigned char const, 18446744073709551615ul>) /root/bitcoin/ephemeralfuzzbuild/src/test/fuzz/../../../../src/test/fuzz/package_eval.cpp:228:27
    18    [#15](/bitcoin-bitcoin/15/) 0x5560e317c8c7 in std::function<void (std::span<unsigned char const, 18446744073709551615ul>)>::operator()(std::span<unsigned char const, 18446744073709551615ul>) const /usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/bits/std_function.h:591:9
    19    [#16](/bitcoin-bitcoin/16/) 0x5560e317c8c7 in LLVMFuzzerTestOneInput /root/bitcoin/ephemeralfuzzbuild/src/test/fuzz/util/../../../../../src/test/fuzz/fuzz.cpp:213:5
    20    [#17](/bitcoin-bitcoin/17/) 0x5560e2df9d00 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/root/bitcoin/ephemeralfuzzbuild/src/test/fuzz/fuzz+0x94ed00) (BuildId: a5b9aaf3b4abf14131d79477c841f1529fb62bf2)
    21    [#18](/bitcoin-bitcoin/18/) 0x5560e2df9435 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) (/root/bitcoin/ephemeralfuzzbuild/src/test/fuzz/fuzz+0x94e435) (BuildId: a5b9aaf3b4abf14131d79477c841f1529fb62bf2)
    22    [#19](/bitcoin-bitcoin/19/) 0x5560e2dfabc5 in fuzzer::Fuzzer::MutateAndTestOne() (/root/bitcoin/ephemeralfuzzbuild/src/test/fuzz/fuzz+0x94fbc5) (BuildId: a5b9aaf3b4abf14131d79477c841f1529fb62bf2)
    23    [#20](/bitcoin-bitcoin/20/) 0x5560e2dfb7c5 in fuzzer::Fuzzer::Loop(std::vector<fuzzer::SizedFile, std::allocator<fuzzer::SizedFile>>&) (/root/bitcoin/ephemeralfuzzbuild/src/test/fuzz/fuzz+0x9507c5) (BuildId: a5b9aaf3b4abf14131d79477c841f1529fb62bf2)
    24    [#21](/bitcoin-bitcoin/21/) 0x5560e2de99ef in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/root/bitcoin/ephemeralfuzzbuild/src/test/fuzz/fuzz+0x93e9ef) (BuildId: a5b9aaf3b4abf14131d79477c841f1529fb62bf2)
    25    [#22](/bitcoin-bitcoin/22/) 0x5560e2e12da2 in main (/root/bitcoin/ephemeralfuzzbuild/src/test/fuzz/fuzz+0x967da2) (BuildId: a5b9aaf3b4abf14131d79477c841f1529fb62bf2)
    26    [#23](/bitcoin-bitcoin/23/) 0x7fc27ba08249  (/lib/x86_64-linux-gnu/libc.so.6+0x27249) (BuildId: 58254ca972028402bc40624f81388d85ec95f70d)
    27    [#24](/bitcoin-bitcoin/24/) 0x7fc27ba08304 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x27304) (BuildId: 58254ca972028402bc40624f81388d85ec95f70d)
    28    [#25](/bitcoin-bitcoin/25/) 0x5560e2ddede0 in _start (/root/bitcoin/ephemeralfuzzbuild/src/test/fuzz/fuzz+0x933de0) (BuildId: a5b9aaf3b4abf14131d79477c841f1529fb62bf2)
    

    They all happen within a few seconds of fuzzing. The errors are non-deterministic, so the inputs aren’t of much use unfortunately 😕 I’m still looking for the bug, but will likely be easier for you.

  10. instagibbs commented at 6:09 pm on November 13, 2024: member
    @marcofleon to be clear this is happening on master or follow-up?
  11. instagibbs commented at 6:13 pm on November 13, 2024: member
    ok replicated on this PR, I’ll track it down
  12. marcofleon commented at 6:14 pm on November 13, 2024: contributor
    Yeah not on master, just this PR.
  13. in src/test/fuzz/package_eval.cpp:336 in 7f0d8633b1 outdated
    332@@ -338,9 +333,6 @@ FUZZ_TARGET(ephemeral_package_eval, .init = initialize_tx_pool)
    333             Assert(!CheckPackageMempoolAcceptResult(txs, result_package, expect_valid, &tx_pool));
    334         }
    335 
    336-        node.validation_signals->SyncWithValidationInterfaceQueue();
    337-        node.validation_signals->UnregisterSharedValidationInterface(txr);
    338-
    339         CheckMempoolEphemeralInvariants(tx_pool);
    340     }
    341 
    


    marcofleon commented at 6:19 pm on November 13, 2024:
    It’s this commit here that’s causing the errors. Seems that this was actually needed.

    instagibbs commented at 7:39 pm on November 13, 2024:
    specifically needs the SyncWithValidationInterfaceQueue, not the unused part.
  14. instagibbs force-pushed on Nov 13, 2024
  15. in src/policy/ephemeral_policy.cpp:13 in 7dc8a0ba1b outdated
     9@@ -10,7 +10,7 @@ bool HasDust(const CTransactionRef& tx, CFeeRate dust_relay_rate)
    10     return std::any_of(tx->vout.cbegin(), tx->vout.cend(), [&](const auto& output) { return IsDust(output, dust_relay_rate); });
    11 }
    12 
    13-bool CheckValidEphemeralTx(const CTransactionRef& tx, CFeeRate dust_relay_rate, CAmount base_fee, CAmount mod_fee, TxValidationState& state)
    14+bool PreCheckValidEphemeralTx(const CTransactionRef& tx, CFeeRate dust_relay_rate, CAmount base_fee, CAmount mod_fee, TxValidationState& state)
    


    naumenkogs commented at 8:23 am on November 14, 2024:

    7dc8a0ba1be86352fa51860af504ed09fba9307e

    What does valid mean in this context? Can’t this word be dropped?


    instagibbs commented at 2:34 pm on November 15, 2024:
    done
  16. in src/test/transaction_tests.cpp:817 in 7020d29e7f outdated
    813@@ -814,9 +814,11 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
    814     CAmount nDustThreshold = 182 * g_dust.GetFeePerK() / 1000;
    815     BOOST_CHECK_EQUAL(nDustThreshold, 546);
    816 
    817-    // Add dust output to take dust slot, still standard!
    818-    t.vout.emplace_back(0, t.vout[0].scriptPubKey);
    819-    CheckIsStandard(t);
    820+    // Add dust outputs up to allowed maximum, still standard!
    


    naumenkogs commented at 8:37 am on November 14, 2024:

    7020d29e7fb276af9877b6767b4bacf1edfe050c

    wanna also check for non-standard if add one more?


    instagibbs commented at 2:01 pm on November 14, 2024:
    we do in the following lines
  17. in src/policy/ephemeral_policy.h:53 in f306a940d2 outdated
    49@@ -50,8 +50,9 @@ bool PreCheckValidEphemeralTx(const CTransaction& tx, CFeeRate dust_relay_rate,
    50 /** Must be called for each transaction(package) if any dust is in the package.
    51  *  Checks that each transaction's parents have their dust spent by the child,
    52  *  where parents are either in the mempool or in the package itself.
    53- *  @returns std::nullopt if all dust is properly spent, or the txid of the violating child spend.
    54+ *  child_state and child_txid set on failure.
    


    naumenkogs commented at 9:02 am on November 14, 2024:

    f306a940d2ba470a13120853ace49509a8e496a6

    looks odd, perhaps a pasting issue.


    instagibbs commented at 2:02 pm on November 14, 2024:
    It’s a sentence fragment, I can touch it up to be grammatically correct

    instagibbs commented at 2:34 pm on November 15, 2024:
    touched up
  18. Rename CheckValidEphemeralTx to PreCheckEphemeralTx 04a614bf9a
  19. Have HasDust and PreCheckValidEphemeralTx take CTransaction 3ed930a1f4
  20. Use std::ranges for ephemeral policy checks 62016b3230
  21. instagibbs force-pushed on Nov 15, 2024
  22. naumenkogs commented at 8:17 am on November 18, 2024: member
    ACK 5679f398e2a3ab8315d39ee674ccb8ad6a8f73c7
  23. in src/policy/ephemeral_policy.cpp:87 in 5679f398e2 outdated
    83         }
    84 
    85         if (!unspent_parent_dust.empty()) {
    86-            return txid;
    87+            child_txid = tx->GetHash();
    88+            child_state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "missing-ephemeral-spends",
    


    hodlinator commented at 2:05 pm on November 19, 2024:

    nit: Could prefix with out_ to communicate that they are out-reference-parameters instead of locals.

    0            out_child_txid = tx->GetHash();
    1            out_child_state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "missing-ephemeral-spends",
    

    instagibbs commented at 6:51 pm on November 20, 2024:
    sure, changed
  24. in src/policy/ephemeral_policy.cpp:72 in 5679f398e2 outdated
    71@@ -63,16 +72,23 @@ std::optional<Txid> CheckEphemeralSpends(const Package& package, CFeeRate dust_r
    72             processed_parent_set.insert(parent_txid);
    


    hodlinator commented at 2:08 pm on November 19, 2024:

    perf nit: Could remove this line if using .insert and checking the return value instead of .contains above as suggested here #30239 (review).

    The current version is slightly easier to read but does an extra lookup. I understand if you want to leave as-is for readability as the perf-hit is probably negligible.


    instagibbs commented at 6:51 pm on November 20, 2024:
    going to leave as is
  25. in src/rpc/mining.cpp:499 in 5679f398e2 outdated
    495@@ -496,7 +496,7 @@ static RPCHelpMan prioritisetransaction()
    496 
    497     // Non-0 fee dust transactions are not allowed for entry, and modification not allowed afterwards
    498     const auto& tx = mempool.get(hash);
    499-    if (tx && HasDust(tx, mempool.m_opts.dust_relay_feerate)) {
    500+    if (mempool.m_opts.require_standard && tx && !GetDust(*tx, mempool.m_opts.dust_relay_feerate).empty()) {
    


    hodlinator commented at 2:20 pm on November 19, 2024:

    Thinking back to discussion around how limiting prioritizetransaction for miners could backfire on the ecosystem in previous PR.

    Encouraging miners to run with -acceptnonstdtxn means all relayfee limits for other transactions are effectively zero. But standardness touches upon other aspects of transactions as well (with more to be added in the future). So this is worse than only pushing miners to zero out relayfee-args/settings. This if-block should probably not have been added in the main PR in the first place.


    instagibbs commented at 6:51 pm on November 20, 2024:

    Setting -dustrelayfee=0 avoids the check much more directly and simply, with no recompilation needed.

    Gating it based on standardness checks is just easier to understand when e.g., standardness isn’t being enforced anyways, so dust should be treated as a no-op.

    I’m going to mark this as resolved. If we want to reverse this logic, imo we should do it in another PR that removes both the logic in prioritisation as well as the modified fee checks.


    hodlinator commented at 10:41 am on November 21, 2024:
    Still worried that this will backfire, but will investigate more and maybe spawn a new PR.

    glozow commented at 11:25 pm on November 22, 2024:
    fwiw I’m not too concerned about this “encouraging” miners to patch. Miners might mine dust and this doesn’t stop them from doing anything, but I don’t think this would make that more likely given “subverting” it would only require -dustrelayfee=0 and has always been possible. I think it’s worth discussing and asking miners. But that’s my thinking.
  26. in src/test/fuzz/package_eval.cpp:228 in 5679f398e2 outdated
    234-            // Note that this test currently only spends package outputs in last transaction.
    235-            bool last_tx = num_txs > 1 && txs.size() == num_txs - 1;
    236-
    237             // Create transaction to add to the mempool
    238-            const CTransactionRef tx = [&] {
    239+            txs.push_back([&] {
    


    hodlinator commented at 2:47 pm on November 19, 2024:

    nit: Could emplace movable CTransaction, apologies for not including it in my original suggestion.

    0            txs.emplace_back([&] {
    

    instagibbs commented at 6:51 pm on November 20, 2024:
    done
  27. in src/test/txvalidation_tests.cpp:146 in 60e18bb2dc outdated
    148-    BOOST_CHECK(CheckEphemeralSpends({grandparent_tx_1, dust_spend, dust_non_spend}, minrelay, pool).has_value());
    149-    BOOST_CHECK(CheckEphemeralSpends({grandparent_tx_1, dust_non_spend}, minrelay, pool).has_value());
    150+    const auto dust_non_spend_txid{dust_non_spend->GetHash()};
    151+    const Txid null_txid;
    152+    assert(dust_non_spend_txid != null_txid);
    153+    BOOST_CHECK_EQUAL(CheckEphemeralSpends({grandparent_tx_1, dust_non_spend, dust_spend}, minrelay, pool).value_or(null_txid), dust_non_spend_txid);
    


    hodlinator commented at 5:03 pm on November 19, 2024:

    In 60e18bb2dcd2c16a64e01023b793b0494cd6ca64:

    nit: (Resolved in later commit) - .value_or(null_txid) seems unnecessary? Suggestion:

    0    BOOST_CHECK_EQUAL(CheckEphemeralSpends({grandparent_tx_1, dust_non_spend, dust_spend}, minrelay, pool), dust_non_spend_txid);
    

    Changing to that convention makes the introduction of null_txid pointless.


    instagibbs commented at 6:51 pm on November 20, 2024:

    IIUC I’d have needed to at least make the RHS an optional to do that?

    Either way, this goes away in a later commit, so I’m going to leave as-s.


    hodlinator commented at 10:44 am on November 21, 2024:

    FYI: https://en.cppreference.com/w/cpp/utility/optional/operator_cmp overloads 21-33

    Okay with leaving as-is.

  28. in src/test/txvalidation_tests.cpp:104 in 263a85023c outdated
     99@@ -100,9 +100,11 @@ static inline CTransactionRef make_ephemeral_tx(const std::vector<COutPoint>& in
    100     for (size_t i{0}; i < inputs.size(); ++i) {
    101         mtx.vin[i].prevout = inputs[i];
    102     }
    103-    for (auto i{0}; i < 3; ++i) {
    104+    int num_outputs{3};
    105+    int dust_index{num_outputs - 1};
    


    hodlinator commented at 5:13 pm on November 19, 2024:

    Should further link dust_index with the value used by callers of the function, as current version has a hidden dependency.

     0diff --git a/src/test/txvalidation_tests.cpp b/src/test/txvalidation_tests.cpp
     1index b362abfa1d..0a51ff411f 100644
     2--- a/src/test/txvalidation_tests.cpp
     3+++ b/src/test/txvalidation_tests.cpp
     4@@ -91,8 +91,10 @@ static inline CTransactionRef make_tx(const std::vector<COutPoint>& inputs, int3
     5 }
     6 
     7 // Same as make_tx but adds 2 normal outputs and 0-value dust to end of vout
     8-static inline CTransactionRef make_ephemeral_tx(const std::vector<COutPoint>& inputs, int32_t version)
     9+static inline CTransactionRef make_ephemeral_tx(const std::vector<COutPoint>& inputs, int32_t version, uint32_t dust_index)
    10 {
    11+    const uint32_t num_outputs{3};
    12+    assert(dust_index < num_outputs);
    13     CMutableTransaction mtx = CMutableTransaction{};
    14     mtx.version = version;
    15     mtx.vin.resize(inputs.size());
    16@@ -100,9 +102,7 @@ static inline CTransactionRef make_ephemeral_tx(const std::vector<COutPoint>& in
    17     for (size_t i{0}; i < inputs.size(); ++i) {
    18         mtx.vin[i].prevout = inputs[i];
    19     }
    20-    int num_outputs{3};
    21-    int dust_index{num_outputs - 1};
    22-    for (auto i{0}; i < num_outputs; ++i) {
    23+    for (uint32_t i{0}; i < num_outputs; ++i) {
    24         mtx.vout[i].scriptPubKey = CScript() << OP_TRUE;
    25         mtx.vout[i].nValue = (i == dust_index) ? 0 : 10000;
    26     }
    27@@ -118,12 +118,12 @@ BOOST_FIXTURE_TEST_CASE(ephemeral_tests, RegTestingSetup)
    28 
    29     CFeeRate minrelay(1000);
    30 
    31+    const uint32_t dust_index = 2;
    32+
    33     // Basic transaction with dust
    34-    auto grandparent_tx_1 = make_ephemeral_tx(random_outpoints(1), /*version=*/2);
    35+    auto grandparent_tx_1 = make_ephemeral_tx(random_outpoints(1), /*version=*/2, dust_index);
    36     const auto dust_txid = grandparent_tx_1->GetHash();
    37 
    38-    uint32_t dust_index = 2;
    39-
    40     // Child transaction spending dust
    41     auto dust_spend = make_tx({COutPoint{dust_txid, dust_index}}, /*version=*/2);
    42 
    43@@ -149,7 +149,7 @@ BOOST_FIXTURE_TEST_CASE(ephemeral_tests, RegTestingSetup)
    44     BOOST_CHECK_EQUAL(CheckEphemeralSpends({grandparent_tx_1, dust_spend, dust_non_spend}, minrelay, pool).value_or(null_txid), dust_non_spend_txid);
    45     BOOST_CHECK_EQUAL(CheckEphemeralSpends({grandparent_tx_1, dust_non_spend}, minrelay, pool).value_or(null_txid), dust_non_spend_txid);
    46 
    47-    auto grandparent_tx_2 = make_ephemeral_tx(random_outpoints(1), /*version=*/2);
    48+    auto grandparent_tx_2 = make_ephemeral_tx(random_outpoints(1), /*version=*/2, dust_index);
    49     const auto dust_txid_2 = grandparent_tx_2->GetHash();
    50 
    51     // Spend dust from one but not another is ok, as long as second grandparent has no child
    52@@ -169,14 +169,14 @@ BOOST_FIXTURE_TEST_CASE(ephemeral_tests, RegTestingSetup)
    53     BOOST_CHECK(!CheckEphemeralSpends({grandparent_tx_1, grandparent_tx_2, dust_spend_all_outpoints}, minrelay, pool));
    54 
    55     // 2 grandparents with dust <- 1 dust-spending parent with dust <- child with no dust
    56-    auto parent_with_dust = make_ephemeral_tx({COutPoint{dust_txid, dust_index}, COutPoint{dust_txid_2, dust_index}}, /*version=*/2);
    57+    auto parent_with_dust = make_ephemeral_tx({COutPoint{dust_txid, dust_index}, COutPoint{dust_txid_2, dust_index}}, /*version=*/2, dust_index);
    58     // Ok for parent to have dust
    59     BOOST_CHECK(!CheckEphemeralSpends({grandparent_tx_1, grandparent_tx_2, parent_with_dust}, minrelay, pool));
    60     auto child_no_dust = make_tx({COutPoint{parent_with_dust->GetHash(), dust_index}}, /*version=*/2);
    61     BOOST_CHECK(!CheckEphemeralSpends({grandparent_tx_1, grandparent_tx_2, parent_with_dust, child_no_dust}, minrelay, pool));
    62 
    63     // 2 grandparents with dust <- 1 dust-spending parent with dust <- child with dust
    64-    auto child_with_dust = make_ephemeral_tx({COutPoint{parent_with_dust->GetHash(), dust_index}}, /*version=*/2);
    65+    auto child_with_dust = make_ephemeral_tx({COutPoint{parent_with_dust->GetHash(), dust_index}}, /*version=*/2, dust_index);
    66     BOOST_CHECK(!CheckEphemeralSpends({grandparent_tx_1, grandparent_tx_2, parent_with_dust, child_with_dust}, minrelay, pool));
    67 
    68     // Tests with parents in mempool
    
     0diff --git a/src/test/txvalidation_tests.cpp b/src/test/txvalidation_tests.cpp
     1index b362abfa1d..2309cd4f4d 100644
     2--- a/src/test/txvalidation_tests.cpp
     3+++ b/src/test/txvalidation_tests.cpp
     4@@ -90,6 +90,8 @@ static inline CTransactionRef make_tx(const std::vector<COutPoint>& inputs, int3
     5     return MakeTransactionRef(mtx);
     6 }
     7 
     8+static constexpr auto EPHEMERAL_DUST_INDEX = 2;
     9+
    10 // Same as make_tx but adds 2 normal outputs and 0-value dust to end of vout
    11 static inline CTransactionRef make_ephemeral_tx(const std::vector<COutPoint>& inputs, int32_t version)
    12 {
    13@@ -100,11 +102,11 @@ static inline CTransactionRef make_ephemeral_tx(const std::vector<COutPoint>& in
    14     for (size_t i{0}; i < inputs.size(); ++i) {
    15         mtx.vin[i].prevout = inputs[i];
    16     }
    17-    int num_outputs{3};
    18-    int dust_index{num_outputs - 1};
    19-    for (auto i{0}; i < num_outputs; ++i) {
    20+    constexpr uint32_t num_outputs{3};
    21+    static_assert(EPHEMERAL_DUST_INDEX < num_outputs);
    22+    for (uint32_t i{0}; i < num_outputs; ++i) {
    23         mtx.vout[i].scriptPubKey = CScript() << OP_TRUE;
    24-        mtx.vout[i].nValue = (i == dust_index) ? 0 : 10000;
    25+        mtx.vout[i].nValue = (i == EPHEMERAL_DUST_INDEX) ? 0 : 10000;
    26     }
    27     return MakeTransactionRef(mtx);
    28 }
    29@@ -122,10 +124,8 @@ BOOST_FIXTURE_TEST_CASE(ephemeral_tests, RegTestingSetup)
    30     auto grandparent_tx_1 = make_ephemeral_tx(random_outpoints(1), /*version=*/2);
    31     const auto dust_txid = grandparent_tx_1->GetHash();
    32 
    33-    uint32_t dust_index = 2;
    34-
    35     // Child transaction spending dust
    36-    auto dust_spend = make_tx({COutPoint{dust_txid, dust_index}}, /*version=*/2);
    37+    auto dust_spend = make_tx({COutPoint{dust_txid, EPHEMERAL_DUST_INDEX}}, /*version=*/2);
    38 
    39     // We first start with nothing "in the mempool", using package checks
    40 
    41@@ -139,7 +139,7 @@ BOOST_FIXTURE_TEST_CASE(ephemeral_tests, RegTestingSetup)
    42     BOOST_CHECK(!CheckEphemeralSpends({grandparent_tx_1, dust_spend}, CFeeRate(0), pool));
    43     BOOST_CHECK(!CheckEphemeralSpends({grandparent_tx_1, dust_spend}, minrelay, pool));
    44 
    45-    auto dust_non_spend = make_tx({COutPoint{dust_txid, dust_index - 1}}, /*version=*/2);
    46+    auto dust_non_spend = make_tx({COutPoint{dust_txid, EPHEMERAL_DUST_INDEX - 1}}, /*version=*/2);
    47 
    48     // Child spending non-dust only from parent should be disallowed even if dust otherwise spent
    49     const auto dust_non_spend_txid{dust_non_spend->GetHash()};
    50@@ -155,11 +155,11 @@ BOOST_FIXTURE_TEST_CASE(ephemeral_tests, RegTestingSetup)
    51     // Spend dust from one but not another is ok, as long as second grandparent has no child
    52     BOOST_CHECK(!CheckEphemeralSpends({grandparent_tx_1, grandparent_tx_2, dust_spend}, minrelay, pool));
    53 
    54-    auto dust_non_spend_both_parents = make_tx({COutPoint{dust_txid, dust_index}, COutPoint{dust_txid_2, dust_index - 1}}, /*version=*/2);
    55+    auto dust_non_spend_both_parents = make_tx({COutPoint{dust_txid, EPHEMERAL_DUST_INDEX}, COutPoint{dust_txid_2, EPHEMERAL_DUST_INDEX - 1}}, /*version=*/2);
    56     // But if we spend from the parent, it must spend dust
    57     BOOST_CHECK_EQUAL(CheckEphemeralSpends({grandparent_tx_1, grandparent_tx_2, dust_non_spend_both_parents}, minrelay, pool).value_or(null_txid), dust_non_spend_both_parents->GetHash());
    58 
    59-    auto dust_spend_both_parents = make_tx({COutPoint{dust_txid, dust_index}, COutPoint{dust_txid_2, dust_index}}, /*version=*/2);
    60+    auto dust_spend_both_parents = make_tx({COutPoint{dust_txid, EPHEMERAL_DUST_INDEX}, COutPoint{dust_txid_2, EPHEMERAL_DUST_INDEX}}, /*version=*/2);
    61     BOOST_CHECK(!CheckEphemeralSpends({grandparent_tx_1, grandparent_tx_2, dust_spend_both_parents}, minrelay, pool));
    62 
    63     // Spending other outputs is also correct, as long as the dusty one is spent
    64@@ -169,14 +169,14 @@ BOOST_FIXTURE_TEST_CASE(ephemeral_tests, RegTestingSetup)
    65     BOOST_CHECK(!CheckEphemeralSpends({grandparent_tx_1, grandparent_tx_2, dust_spend_all_outpoints}, minrelay, pool));
    66 
    67     // 2 grandparents with dust <- 1 dust-spending parent with dust <- child with no dust
    68-    auto parent_with_dust = make_ephemeral_tx({COutPoint{dust_txid, dust_index}, COutPoint{dust_txid_2, dust_index}}, /*version=*/2);
    69+    auto parent_with_dust = make_ephemeral_tx({COutPoint{dust_txid, EPHEMERAL_DUST_INDEX}, COutPoint{dust_txid_2, EPHEMERAL_DUST_INDEX}}, /*version=*/2);
    70     // Ok for parent to have dust
    71     BOOST_CHECK(!CheckEphemeralSpends({grandparent_tx_1, grandparent_tx_2, parent_with_dust}, minrelay, pool));
    72-    auto child_no_dust = make_tx({COutPoint{parent_with_dust->GetHash(), dust_index}}, /*version=*/2);
    73+    auto child_no_dust = make_tx({COutPoint{parent_with_dust->GetHash(), EPHEMERAL_DUST_INDEX}}, /*version=*/2);
    74     BOOST_CHECK(!CheckEphemeralSpends({grandparent_tx_1, grandparent_tx_2, parent_with_dust, child_no_dust}, minrelay, pool));
    75 
    76     // 2 grandparents with dust <- 1 dust-spending parent with dust <- child with dust
    77-    auto child_with_dust = make_ephemeral_tx({COutPoint{parent_with_dust->GetHash(), dust_index}}, /*version=*/2);
    78+    auto child_with_dust = make_ephemeral_tx({COutPoint{parent_with_dust->GetHash(), EPHEMERAL_DUST_INDEX}}, /*version=*/2);
    79     BOOST_CHECK(!CheckEphemeralSpends({grandparent_tx_1, grandparent_tx_2, parent_with_dust, child_with_dust}, minrelay, pool));
    80 
    81     // Tests with parents in mempool
    

    instagibbs commented at 6:51 pm on November 20, 2024:
    took modified version of file-local constant
  29. in src/test/fuzz/package_eval.cpp:239 in 0f542e4bd5 outdated
    248+                bool last_tx = num_txs > 1 && txs.size() == num_txs - 1;
    249+                const auto num_in = outpoint_to_rbf ? 2 :
    250                     last_tx ? fuzzed_data_provider.ConsumeIntegralInRange<int>(package_outpoints.size()/2 + 1, package_outpoints.size()) :
    251                     fuzzed_data_provider.ConsumeIntegralInRange<int>(1, 4);
    252-                auto num_out = should_rbf_eph_spend ? 1 : fuzzed_data_provider.ConsumeIntegralInRange<int>(1, 4);
    253+                auto num_out = outpoint_to_rbf ? 1 : fuzzed_data_provider.ConsumeIntegralInRange<int>(1, 4);
    


    hodlinator commented at 11:11 pm on November 19, 2024:
    nit: Could add const to num_out for symmetry with num_in as you are touching this line (pointed out in #30239 (review)).

    instagibbs commented at 6:51 pm on November 20, 2024:
    done
  30. in src/test/txvalidation_tests.cpp:159 in 0f542e4bd5 outdated
    161-    BOOST_CHECK(CheckEphemeralSpends({grandparent_tx_1, dust_non_spend, dust_spend}, minrelay, pool).has_value());
    162-    BOOST_CHECK(CheckEphemeralSpends({grandparent_tx_1, dust_spend, dust_non_spend}, minrelay, pool).has_value());
    163-    BOOST_CHECK(CheckEphemeralSpends({grandparent_tx_1, dust_non_spend}, minrelay, pool).has_value());
    164+    const auto dust_non_spend_txid{dust_non_spend->GetHash()};
    165+    const Txid null_txid;
    166+    assert(dust_non_spend_txid != null_txid);
    


    hodlinator commented at 11:16 pm on November 19, 2024:
    In 0f92fa2d468186a1526827a063f66e3042e028dc: No longer used, should probably be removed there.

    instagibbs commented at 6:51 pm on November 20, 2024:
    removed
  31. in src/policy/policy.cpp:156 in 0f542e4bd5 outdated
    149@@ -142,13 +150,11 @@ bool IsStandardTx(const CTransaction& tx, const std::optional<unsigned>& max_dat
    150         else if ((whichType == TxoutType::MULTISIG) && (!permit_bare_multisig)) {
    151             reason = "bare-multisig";
    152             return false;
    153-        } else if (IsDust(txout, dust_relay_fee)) {
    154-            num_dust_outputs++;
    155         }
    156     }
    157 
    158     // Only MAX_DUST_OUTPUTS_PER_TX dust is permitted(on otherwise valid ephemeral dust)
    


    hodlinator commented at 11:34 pm on November 19, 2024:

    nit:

    0    // Only MAX_DUST_OUTPUTS_PER_TX dust is permitted (on otherwise valid ephemeral dust)
    

    instagibbs commented at 6:50 pm on November 20, 2024:
    leaving as is
  32. hodlinator changes_requested
  33. hodlinator commented at 11:45 pm on November 19, 2024: contributor

    Reviewed 5679f398e2a3ab8315d39ee674ccb8ad6a8f73c7

    Especially like the refactor of CheckEphemeralSpends() with less surprising return/out-values.

    Good to see LIMITED_WHILE(fuzzed_data_provider.remaining_bytes() > 0 in more places than I suggested.

    Suggested changes aside from inline comments:

    03ec3f6230f440b264abe3aa42a57fdd29bd3ba3 commit message

    0- Implement GetDust to replace HasDust, use where appropriate
    1+ Move+rename GetDustIndexes -> GetDust to replace HasDust, use where appropriate
    

    Deduplicate assert_mempool_contents()

    As pointed out by theStack & me:

     0diff --git a/test/functional/mempool_package_rbf.py b/test/functional/mempool_package_rbf.py
     1index a5b8fa5f87..14194f9e1a 100755
     2--- a/test/functional/mempool_package_rbf.py
     3+++ b/test/functional/mempool_package_rbf.py
     4@@ -19,6 +19,7 @@ from test_framework.wallet import (
     5     DEFAULT_FEE,
     6     MiniWallet,
     7 )
     8+from test_framework import mempool_util
     9 
    10 MAX_REPLACEMENT_CANDIDATES = 100
    11 
    12@@ -37,15 +38,7 @@ class PackageRBFTest(BitcoinTestFramework):
    13         ]] * self.num_nodes
    14 
    15     def assert_mempool_contents(self, expected=None):
    16-        """Assert that all transactions in expected are in the mempool,
    17-        and no additional ones exist.
    18-        """
    19-        if not expected:
    20-            expected = []
    21-        mempool = self.nodes[0].getrawmempool(verbose=False)
    22-        assert_equal(len(mempool), len(expected))
    23-        for tx in expected:
    24-            assert tx.rehash() in mempool
    25+        mempool_util.assert_mempool_contents(self, self.nodes[0], expected, sync=False)
    26 
    27     def create_simple_package(self, parent_coin, parent_fee=DEFAULT_FEE, child_fee=DEFAULT_CHILD_FEE, heavy_child=False):
    28         """Create a 1 parent 1 child package using the coin passed in as the parent's input. The
    

    + Sanity check for assert_mempool_contents()

    Could add sanity check if passing same tx twice in expected (https://github.com/bitcoin/bitcoin/pull/30239#discussion_r1831120099)

     0diff --git a/test/functional/test_framework/mempool_util.py b/test/functional/test_framework/mempool_util.py
     1index e04ae914cc..72da52d957 100644
     2--- a/test/functional/test_framework/mempool_util.py
     3+++ b/test/functional/test_framework/mempool_util.py
     4@@ -30,6 +30,9 @@ def assert_mempool_contents(test_framework, node, expected=None, sync=True):
     5         test_framework.sync_mempools()
     6     if not expected:
     7         expected = []
     8+    else:
     9+        # Sanity check that elements are unique.
    10+        assert_equal(len(expected), len(set(expected)))
    11     mempool = node.getrawmempool(verbose=False)
    12     assert_equal(len(mempool), len(expected))
    13     for tx in expected:
    
  34. Move+rename GetDustIndexes -> GetDust
    Use to replace HasDust and where appropraite
    c6859ce2de
  35. ephemeral policy: IWYU dd9044b8d4
  36. ephemeral policy doxygen cleanup c5c10fd317
  37. bench: remove unnecessary CMTxn constructors ef94d84b4e
  38. unit test: assert txid returned on CheckEphemeralSpends failures
    Simplify nullopt checks
    5fbcfd12b8
  39. unit test: make dust index less magical 15b6cbf07f
  40. fuzz: remove dangling reference to GetEntry bc0d98ea61
  41. fuzz: explain package eval coin tracking better c041ad6ecc
  42. fuzz: Directly place transactions in vector bedca1cb66
  43. func: cleanup test_dustrelay comments 768a0c1889
  44. func: cleanup reorg test comment 09ce926e4a
  45. fuzz: remove unused TransactionsDelta validation interface 4dfdf615b9
  46. fuzz: use optional status instead of should_rbf_eph_spend 445eaed182
  47. fuzz: package_eval: move last_tx inside txn ctor 7c3490169c
  48. unit test: adapt to changing MAX_DUST_OUTPUTS_PER_TX ca050d12e7
  49. RPC: only enforce dust rules on priority when standardness active 08e969bd10
  50. func: slight elaboration on submitpackage restriction e5709a4a41
  51. func: rename test_free_relay to test_no_minrelay_fee 87b26e3dc0
  52. CheckEphemeralSpends: no need to iterate inputs if no parent dust d9cfa5fc4e
  53. unit test: ephemeral_tests is using a dust relay rate, not minrelay 8424290304
  54. func: add note about lack of 1P1C propagation in tree submitpackage cf0cee1617
  55. CheckEphemeralSpends: return boolean, and set child state and txid outparams ba35a570c5
  56. fuzz: package_eval: let fuzzer run out input in main tx creation loop d033acb608
  57. functional: only generate required blocks for test ea5db2f269
  58. assert_mempool_contents: assert not duplicates expected 466e4df3fb
  59. instagibbs force-pushed on Nov 20, 2024
  60. instagibbs commented at 6:51 pm on November 20, 2024: member

    reworked https://github.com/bitcoin/bitcoin/commit/03ec3f6230f440b264abe3aa42a57fdd29bd3ba3 commit message

    Deduplicate assert_mempool_contents() Deferring to future work since that’s a different test, I’ll review it if someone opens a clenaup PR.

    Sanity check for assert_mempool_contents()

    Good idea, added minimal diff

  61. naumenkogs commented at 6:31 am on November 21, 2024: member

    ACK 466e4df3fb83ef82b6add22e202e3a70dbf83a12

    a trivial refactoring since the last ack

  62. hodlinator approved
  63. hodlinator commented at 9:46 pm on November 21, 2024: contributor

    ACK 466e4df3fb83ef82b6add22e202e3a70dbf83a12

    Mostly responded to my feedback since my last review.

    Compiled with BDB and passed functional tests, unittests and ran ephemeral_package_eval fuzz target for 1 minute.

    Still have reservations about the prioritisetransaction RPC, but not blocking.

  64. achow101 referenced this in commit 2638fdb4f9 on Nov 22, 2024
  65. glozow commented at 11:33 pm on November 22, 2024: member
    cc @stickies-v, many of your comments
  66. in src/test/fuzz/package_eval.cpp:213 in d033acb608 outdated
    209@@ -210,7 +210,7 @@ FUZZ_TARGET(ephemeral_package_eval, .init = initialize_tx_pool)
    210 
    211     chainstate.SetMempool(&tx_pool);
    212 
    213-    LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 300)
    214+    LIMITED_WHILE(fuzzed_data_provider.remaining_bytes() > 0, 300)
    


    glozow commented at 11:34 pm on November 22, 2024:
    Why is using remaining_bytes() better here? I didn’t get that impression from reading #30239 (review)

    glozow commented at 4:56 pm on November 25, 2024:
    oh edit, i see now image
  67. in src/policy/policy.cpp:70 in c6859ce2de outdated
    66@@ -67,6 +67,15 @@ bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFeeIn)
    67     return (txout.nValue < GetDustThreshold(txout, dustRelayFeeIn));
    68 }
    69 
    70+std::vector<uint32_t> GetDust(const CTransaction& tx, CFeeRate dust_relay_rate)
    


    theStack commented at 8:47 pm on November 24, 2024:
    nit: imho the name GetDustIndexes was fine and more expressive, but no strong feelings
  68. theStack approved
  69. theStack commented at 8:57 pm on November 24, 2024: contributor

    lgtm ACK 466e4df3fb83ef82b6add22e202e3a70dbf83a12

    If you need to retouch, could also tackle #30239 (review) (e.g. put it into c5c10fd317c6b4c033f3001757e6975b8b9a4942)

  70. in src/policy/policy.h:135 in 466e4df3fb
    130@@ -131,6 +131,8 @@ bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFee);
    131 
    132 bool IsStandard(const CScript& scriptPubKey, const std::optional<unsigned>& max_datacarrier_bytes, TxoutType& whichType);
    133 
    134+/** Get the vout index numbers of all dust outputs */
    135+std::vector<uint32_t> GetDust(const CTransaction& tx, CFeeRate dust_relay_rate);
    


    glozow commented at 4:49 pm on November 25, 2024:
    Why not CTransactionRef?
  71. in src/policy/ephemeral_policy.cpp:8 in 3ed930a1f4 outdated
    4@@ -5,12 +5,12 @@
    5 #include <policy/ephemeral_policy.h>
    6 #include <policy/policy.h>
    7 
    8-bool HasDust(const CTransactionRef& tx, CFeeRate dust_relay_rate)
    9+bool HasDust(const CTransaction& tx, CFeeRate dust_relay_rate)
    


    glozow commented at 4:50 pm on November 25, 2024:
    Why not CTransactionRef? (3ed930a1f41f7d7160c6ede5dcf3d4d5f1cfa876)
  72. glozow commented at 4:58 pm on November 25, 2024: member
    utACK 466e4df3fb83ef82b6add22e202e3a70dbf83a12
  73. glozow merged this on Nov 25, 2024
  74. glozow closed this on Nov 25, 2024


github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2024-12-21 15:12 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me