fees: make the class FeeFilterRounder thread-safe #24407

pull vasild wants to merge 3 commits into bitcoin:master from vasild:FeeFilterRounder_thread_safe changing 2 files +29 −12
  1. vasild commented at 4:21 pm on February 21, 2022: contributor

    Make the class FeeFilterRounder thread-safe so that its methods can be called concurrently by different threads on the same object. Currently it has just one method (round()).

    The second commit is optional, but it improves readability, showing that the feeset member will never be changed, thus does not need protection from concurrent access.

  2. vasild commented at 4:23 pm on February 21, 2022: contributor

    This is revived from the original version of #19268 (cc @hebasto, @ajtowns).

    This achieves the same purpose as #22053, but in a different way (cc @MarcoFalke).

    My reasoning for opening this PR is that #19268 was reduced to just a comment because it is easier to just document the non-thread safe nature of FeeFilterRounder. But #22053 goes beyond that, trying to use it in a thread-safe way. I think it is best to make FeeFilterRounder thread-safe itself, so that it can be used without thread-safety-worries now and in the future if used in new places.

  3. DrahtBot added the label TX fees and policy on Feb 21, 2022
  4. maflcko commented at 8:57 am on February 22, 2022: member

    This achieves the same purpose as #22053, but in a different way (cc @MarcoFalke).

    I don’t think the two pulls achieve the same goal. In fact I think they are completely orthogonal:

    • This pull makes a utility class thread safe, so that it may be called in a concurrent context without running into UB
    • The other pull aims to reduce the use of the cs_main “global” consistency lock. The consistency lock is needed even in the absence of UB. Also, m_insecure_rand_mutex added here can’t possibly achieve what cs_main achieves right now in MaybeSendFeefilter.

    So I think the two pull requests are best reviewed and evaluated independently. Also, there is no dependency between them. Either can be merged before the other, or not at all.

  5. in src/policy/fees.cpp:1005 in ecb5e10247 outdated
    1002+static std::set<double> MakeFeeSet(const CFeeRate& min_incremental_fee,
    1003+                                   double max_filter_feerate,
    1004+                                   double fee_filter_spacing)
    1005 {
    1006-    CAmount minFeeLimit = std::max(CAmount(1), minIncrementalFee.GetFeePerK() / 2);
    1007+    std::set<double> feeset;
    


    jonatack commented at 5:36 pm on March 14, 2022:
    ecb5e10247a80356e1d22c2970e8c9b8fabff486 style nit, the second commit would have been marginally easier to review without the localvar style renamings but since you rename them here, may as well also update feeset to fee_set in MakeFeeSet() (optionally the class data member too) so that they are all per current style in that function.

    vasild commented at 4:03 pm on March 15, 2022:
    Done, renames in a separate commit.
  6. jonatack commented at 5:41 pm on March 14, 2022: contributor

    ACK ecb5e10247a80356e1d22c2970e8c9b8fabff486

    The first commit message should be fixed from “Co-authoread-by:” to “Co-authored-by:”

  7. in src/policy/fees.cpp:1007 in ecb5e10247 outdated
    1004+                                   double fee_filter_spacing)
    1005 {
    1006-    CAmount minFeeLimit = std::max(CAmount(1), minIncrementalFee.GetFeePerK() / 2);
    1007+    std::set<double> feeset;
    1008+
    1009+    CAmount min_fee_limit = std::max(CAmount(1), min_incremental_fee.GetFeePerK() / 2);
    


    jonatack commented at 5:50 pm on March 14, 2022:

    ecb5e10247a80356e1d22c2970e8c9b8fabff486 if you retouch

    0    const CAmount min_fee_limit{std::max(CAmount(1), min_incremental_fee.GetFeePerK() / 2)};
    

    vasild commented at 4:03 pm on March 15, 2022:
    Done.
  8. vasild force-pushed on Mar 15, 2022
  9. vasild commented at 4:02 pm on March 15, 2022: contributor

    ecb5e10247...b2311fe154: address suggestions

    Invalidates ACK from @jonatack

  10. jonatack commented at 11:56 pm on March 15, 2022: contributor
    ACK b2311fe154dbe3cdc5fac2cf65205ae25f20c8df
  11. in src/policy/fees.cpp:1013 in adfd07564d outdated
    1009@@ -1010,7 +1010,8 @@ FeeFilterRounder::FeeFilterRounder(const CFeeRate& minIncrementalFee)
    1010 CAmount FeeFilterRounder::round(CAmount currentMinFee)
    1011 {
    1012     std::set<double>::iterator it = feeset.lower_bound(currentMinFee);
    1013-    if ((it != feeset.begin() && insecure_rand.rand32() % 3 != 0) || it == feeset.end()) {
    1014+    const auto rand = WITH_LOCK(m_insecure_rand_mutex, return insecure_rand.rand32());
    


    promag commented at 6:34 pm on April 8, 2022:

    adfd07564d5544f327d7432faddcf9612a6a22b3

    Just noting that now now rand32() is always called.


    ajtowns commented at 6:09 pm on April 12, 2022:

    Could have

    0    bool PreferLower() { LOCK(m_insecure_rand_mutex); return insecure_rand.rand32() % 3 != 0; }
    1
    2    if (it != m_fee_set.begin() && PreferLower() || it == m_fee_set.end()) --it;
    

    vasild commented at 7:05 am on April 15, 2022:
    Done, thanks!
  12. promag approved
  13. promag commented at 6:50 pm on April 8, 2022: member
    Code review ACK b2311fe154dbe3cdc5fac2cf65205ae25f20c8df
  14. vasild force-pushed on Apr 15, 2022
  15. vasild commented at 7:04 am on April 15, 2022: contributor

    b2311fe154...f69670bfc2: call rand32() only if necessary

    Invalidates ACKs from @jonatack, @promag

  16. in src/policy/fees.cpp:1031 in f69670bfc2 outdated
    1034+    std::set<double>::iterator it = m_fee_set.lower_bound(currentMinFee);
    1035+    const auto PreferLower = [this]() -> bool {
    1036+        LOCK(m_insecure_rand_mutex);
    1037+        return insecure_rand.rand32() % 3 != 0;
    1038+    };
    1039+    if (it == m_fee_set.end() || (it != m_fee_set.begin() && PreferLower())) {
    


    jonatack commented at 12:17 pm on April 15, 2022:

    (This alternative is more straightforward to my eye. Feel free to ignore.)

    0-    const auto PreferLower = [this]() -> bool {
    1-        LOCK(m_insecure_rand_mutex);
    2-        return insecure_rand.rand32() % 3 != 0;
    3-    };
    4-    if (it == m_fee_set.end() || (it != m_fee_set.begin() && PreferLower())) {
    5+    if (it == m_fee_set.end() || (it != m_fee_set.begin() && WITH_LOCK(m_insecure_rand_mutex, return insecure_rand.rand32()) % 3) {
    

    Ahmadchurra681 commented at 12:22 pm on April 15, 2022:
    Legally help for the safety of worlds

    ajtowns commented at 10:00 pm on April 15, 2022:
    You already have a class just for this logic; seems weird to use a lambda when you could just have a dedicated method? (Having a separate function makes the if line easier to read IMO – the github comment already requires scrolling) shrug

    vasild commented at 8:53 am on April 18, 2022:

    Alright, dropped the function and used WITH_LOCK(). I wrapped the line coz long lines arehardtoreadandrequirescrolling in someenvironments (e.g.github) and also when a single piece of it is changed, then the whole line appears as changed in diffs - see the diff at the bottom of #15936 (review) for example.

    In other words, I agree it is better to be purple, but I like the blueish tint.


    jonatack commented at 9:45 am on April 18, 2022:

    Making review more difficult on the platform of a trusted third party could be considered a feature :smiling_imp:

    (I find one line more readable but not a deal breaker, thanks for updating.)

  17. jonatack commented at 12:19 pm on April 15, 2022: contributor
    ACK f69670bfc2b62c5e59b559726bf16c842e9f0f2e
  18. fees: make the class FeeFilterRounder thread-safe
    So that its methods can be called concurrently by different threads on
    the same object. Currently it has just one method (`round()`).
    
    Co-authored-by: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com>
    e7a5bf6be7
  19. fees: make FeeFilterRounder::feeset const
    It is only set in the constructor, thus improve readability by marking
    it as `const` and setting it from the initializer list using a helper
    function to derive its value.
    
    The idea was suggested by Anthony Towns <aj@erisian.com.au> in
    https://github.com/bitcoin/bitcoin/pull/19268#discussion_r439929792
    8b4ad203d0
  20. style: rename variables to match coding style
    Rename the variables that were touched by the previous commit (split
    logical from style changes).
    
    minIncrementalFee -> min_incremental_fee
    minFeeLimit -> min_fee_limit
    bucketBoundary -> bucket_boundary
    feeset -> fee_set
    FeeFilterRounder::feeset -> FeeFilterRounder::m_fee_set
    8173f160e0
  21. vasild force-pushed on Apr 18, 2022
  22. vasild commented at 8:50 am on April 18, 2022: contributor
    f69670bfc2...8173f160e0: rebase and address suggestion.
  23. jonatack commented at 9:45 am on April 18, 2022: contributor
    re-ACK 8173f160e085186c9bcc7f3506205c309ee66af6
  24. promag approved
  25. promag commented at 10:38 am on April 19, 2022: member
    Code review ACK 8173f160e085186c9bcc7f3506205c309ee66af6
  26. laanwj commented at 1:47 pm on April 19, 2022: member
    Code review ACK 8173f160e085186c9bcc7f3506205c309ee66af6
  27. DrahtBot commented at 12:59 pm on September 23, 2022: contributor

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

    Conflicts

    No conflicts as of last run.

  28. achow101 merged this on Oct 13, 2022
  29. achow101 closed this on Oct 13, 2022

  30. mzumsande commented at 6:08 pm on October 13, 2022: contributor

    CI currently fails on master, probably in connection with this:

    0policy/fees.cpp:1042:10: error: calling function 'MaybeCheckNotHeld' requires negative capability '!m_insecure_rand_mutex' [-Werror,-Wthread-safety-analysis]
    1         WITH_LOCK(m_insecure_rand_mutex, return insecure_rand.rand32()) % 3 != 0)) {
    

    (https://github.com/bitcoin/bitcoin/runs/8876014446)

  31. achow101 referenced this in commit deeb70a165 on Oct 13, 2022
  32. vasild deleted the branch on Oct 14, 2022
  33. sidhujag referenced this in commit a29560945b on Oct 23, 2022
  34. sidhujag referenced this in commit 867554743b on Oct 23, 2022
  35. bitcoin locked this on Oct 14, 2023

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 18:12 UTC

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