[mempool] Allow one extra single-ancestor transaction per package #15681

pull TheBlueMatt wants to merge 1 commits into bitcoin:master from TheBlueMatt:2019-03-lightning-policy changing 4 files +108 −1
  1. TheBlueMatt commented at 3:28 am on March 28, 2019: member

    This implements the proposed policy change from [1], which allows certain classes of contract protocols involving revocation punishments to use CPFP. Note that some such use-cases may still want some form of one-deep package relay, though even this alone may greatly simplify some lightning fee negotiation.

    [1] https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-November/016518.html

  2. fanquake added the label Mempool on Mar 28, 2019
  3. DrahtBot commented at 5:51 am on March 28, 2019: member

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

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #16409 (Remove mempool expiry, treat txs as replaceable instead by MarcoFalke)
    • #16401 (Package relay by sdaftuar)
    • #16400 ([refactor] Rewrite AcceptToMemoryPoolWorker() using smaller parts by sdaftuar)
    • #16398 (rpc: testmempoolaccept for list of transactions by MarcoFalke)
    • #15921 (Tidy up ValidationState interface by jnewbery)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

  4. in src/validation.cpp:769 in e7e46b3001 outdated
    765+            setAncestors.clear();
    766+            // If the new transaction is relatively small (up to 40k weight)
    767+            // and has at most one ancestor (ie ancestor limit of 2, including
    768+            // the new transaction), allow it if its parent has exactly the
    769+            // descendant limit descendants.
    770+            if (nSize <= 10000 && !pool.CalculateMemPoolAncestors(entry, setAncestors, 2, 1000000, nLimitDescendants + 1, nLimitDescendantSize + 10000, errString)) {
    


    instagibbs commented at 4:23 pm on March 28, 2019:
    I’m still chewing on the comment above, but doesn’t this line let transactions >40k weight through no matter what?

    TheBlueMatt commented at 5:04 pm on March 28, 2019:
    Lol, oops, one of these days I’ll learn to code.

    instagibbs commented at 5:07 pm on March 28, 2019:
    did the tests work? ;D

    jachiang commented at 12:41 pm on July 1, 2019:

    @TheBlueMatt I have a spill-over question from the PR review club which covered this PR last week. I am unsure of why the LimitAncestorSize for the carve-out tx has been increased to the block-size.

    EDIT: @harding has helped tidy up my understanding of this:

    In the case of a (to-be-fee-bumped) LN parent TX with two hooks (A and B), which is close or equal to the descendant-size-limit, only a single (carve-out) child can be accepted, since the initial package size limit has been reached with the parent TX alone. This would seem like a race between A and B for the carve-out.

    In regards to the 1M ancestor-size-limit for the carve-out, is it increased to 1M to prevent the ancestor-size-limit from interfering with the carve-out? I suppose this prevents a custom ancestor-size-limit setting from blocking the carve-out and subsequent network propagation.


    TheBlueMatt commented at 2:13 am on July 2, 2019:
    Indeed, we don’t really care about the size of the ancestor transaction here (its limited to the standard single-tx size limit, or 100k today), so I just set it to 1M, we already check that there is only, at max, one unconfirmed parent.
  5. TheBlueMatt force-pushed on Mar 28, 2019
  6. in test/functional/mempool_package_onemore.py:80 in a3053fd871 outdated
    74+        # ...even if it chains on to two parent transactions with one in the chain.
    75+        assert_raises_rpc_error(-26, "too-long-mempool-chain", self.chain_transaction, self.nodes[0], [chain[0][0], second_chain], [1, 0], chain[0][1] + second_chain_value, fee, 1)
    76+        # But not if it chains directly off the first transaction
    77+        self.chain_transaction(self.nodes[0], [chain[0][0]], [1], chain[0][1], fee, 1)
    78+        # and the second chain should work just fine
    79+        self.chain_transaction(self.nodes[0], [second_chain], [0], second_chain_value, fee, 1)
    


    instagibbs commented at 5:07 pm on March 28, 2019:
    Add a test that blowing the 40k weight makes it fail?

    TheBlueMatt commented at 5:59 pm on March 28, 2019:
    Done!

    jnewbery commented at 8:39 pm on July 22, 2019:

    I don’t think this addresses the edge case that we want. The line you added above:

    assert_raises_rpc_error(-26, "too-long-mempool-chain", self.chain_transaction, self.nodes[0], [chain[0][0]], [1], chain[0][1], fee, 350)

    Fails both the nSize > EXTRA_DESCENDANT_TX_SIZE_LIMIT and !pool.CalculateMemPoolAncestors(entry, setAncestors, 2, nLimitAncestorSize, nLimitDescendants + 1, nLimitDescendantSize + EXTRA_DESCENDANT_TX_SIZE_LIMIT, errString) checks. We want a test that differentitates just the weight > 40k case.

  7. TheBlueMatt force-pushed on Mar 28, 2019
  8. TheBlueMatt commented at 6:20 pm on March 28, 2019: member
  9. TheBlueMatt force-pushed on Mar 28, 2019
  10. in test/functional/mempool_package_onemore.py:5 in 891ae7b1c4 outdated
    0@@ -0,0 +1,87 @@
    1+#!/usr/bin/env python3
    2+# Copyright (c) 2014-2019 The Bitcoin Core developers
    3+# Distributed under the MIT software license, see the accompanying
    4+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
    5+"""Test descendant package tracking carge-out allowing one final transaction in
    


    practicalswift commented at 7:35 am on April 2, 2019:
    Should be “carve” :-)
  11. in test/functional/mempool_package_onemore.py:28 in 891ae7b1c4 outdated
    23+    def skip_test_if_missing_module(self):
    24+        self.skip_if_no_wallet()
    25+
    26+    # Build a transaction that spends parent_txid:vout
    27+    # Return amount sent
    28+    def chain_transaction(self, node, parent_txids, vouts, value, fee, num_outputs):
    


    practicalswift commented at 7:37 am on April 2, 2019:
    Nit: This method doesn’t use self: could be made a function?

    jnewbery commented at 8:22 pm on July 22, 2019:
    agree that this would be better as a function than a method
  12. in test/functional/mempool_package_onemore.py:34 in 891ae7b1c4 outdated
    29+        send_value = satoshi_round((value - fee)/num_outputs)
    30+        inputs = []
    31+        for (txid, vout) in zip(parent_txids, vouts):
    32+            inputs.append({'txid' : txid, 'vout' : vout})
    33+        outputs = {}
    34+        for i in range(num_outputs):
    


    practicalswift commented at 7:38 am on April 2, 2019:
    Nit: for _ is more idiomatic when _ is unused :-) Applies also for the other for i:s below :-)
  13. in src/validation.cpp:617 in 891ae7b1c4 outdated
    760@@ -761,7 +761,14 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
    761         size_t nLimitDescendantSize = gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT)*1000;
    762         std::string errString;
    763         if (!pool.CalculateMemPoolAncestors(entry, setAncestors, nLimitAncestors, nLimitAncestorSize, nLimitDescendants, nLimitDescendantSize, errString)) {
    764-            return state.DoS(0, false, REJECT_NONSTANDARD, "too-long-mempool-chain", false, errString);
    765+            setAncestors.clear();
    766+            // If the new transaction is relatively small (up to 40k weight)
    767+            // and has at most one ancestor (ie ancestor limit of 2, including
    768+            // the new transaction), allow it if its parent has exactly the
    769+            // descendant limit descendants.
    


    morcos commented at 3:48 pm on April 11, 2019:
    Please expand significantly on the rationale for this change because its a weird little bit of added complication, and basically the only downside is people not understanding why it’s there. You could link to the mailing list post maybe.
  14. DrahtBot added the label Needs rebase on May 4, 2019
  15. TheBlueMatt force-pushed on Jun 5, 2019
  16. DrahtBot removed the label Needs rebase on Jun 5, 2019
  17. TheBlueMatt force-pushed on Jul 2, 2019
  18. TheBlueMatt commented at 2:13 am on July 2, 2019: member
    Resolved comments.
  19. rustyrussell approved
  20. rustyrussell commented at 3:18 am on July 2, 2019: contributor

    Concept Ack.

    After much discussion, this does seem to be the minimal-intervention fix. Thanks Matt.

  21. sdaftuar commented at 6:30 pm on July 3, 2019: member

    Concept ACK.

    I did some review and light testing, and I noticed that there seems to be a general problem with our RBF logic: if we have some parent transaction whose descendant count is maxed out in the mempool, then we’re unable to rbf any child transaction, because we evaluate the descendant limits of a new transactions ancestors prior to looking at what might be evicted by that transaction. (However, we can generally RBF the parent itself!)

    So in particular, that means that the new transaction that would be carved out by this policy would not be able to be RBF’ed in the situation that the parent transactions’ descendant limit has been reached.

    I’m guessing we may want to fix that to provide additional footgun protection to users that would take advantage of this new behavior, though I’ll leave it to the PR author to decide if it is worth doing in this PR or separately.

  22. ajtowns commented at 9:15 am on July 8, 2019: member

    Concept ACK. Might be worth adding an explicit test case for RBF case @sdaftuar points out:

             # But not if it chains directly off the first transaction
             self.chain_transaction(self.nodes[0], [chain[0][0]], [1], chain[0][1], fee, 1)
    +
    +        # Sadly, RBFing that should fail, however
    +        assert_raises_rpc_error(-26, "too-long-mempool-chain", self.chain_transaction, 0, [chain[0][0]], [1], chain[0][1], fee*2, 1)
    +
             # and the second chain should work just fine
             self.chain_transaction(self.nodes[0], [second_chain], [0], second_chain_value, fee, 1)
    

    (means createrawtransaction needs to be called with replaceable=True as well)

    Could change chain_transaction(self, node, ...) to always use node=self.nodes[0] which would simplify calls, and deal with @practicalswift’s nit.

    Could define a const for the 10k magic number. Is there any reason to have 1M instead of reusing nLimitAncestorSize? (Could not allow the carve out at all if nLimitAncestors <= 1 though that’s probably getting a bit ridiculous)

    I think this should work for two-party lightning channels, because the outputs will be a bunch of CSV-limited ones that won’t be in the mempool, and one CPFP output for each party. So at most one output can be spammed, and that only up to the descendent limit, so the plus-one here should work fine. If there were three or more immediately-spendable outputs (for channel factories and multiparty eltoo eg), I don’t think this would be enough. But that’s fine today.

    I guess it’s not very useful to log when this carve out triggers – it’s meant to prevent attacks from being effective, so while it’s there there won’t be any attacks so it’ll hardly ever be used, but if it weren’t there there would be attacks and it would be useful.

    Should this carve out be limited to only apply when it’s actually raising the parent’s effective fee rate? I think you’d have to loop over all the descendents of your parent, work out the best ancestor fee rate of any of them, then see if the new tx and the parent have a better combined fee rate than that. That seems like it would add a chunk of complexity though, so probably isn’t worth it.

    This seems like it’s a sufficient workaround for current problems, and is a pretty minimal change, while doing anything much better would be lots more complicated. So: Approach ACK.

  23. in test/functional/mempool_package_onemore.py:21 in f1facdd3e2 outdated
    16+MAX_DESCENDANTS = 25
    17+
    18+class MempoolPackagesTest(BitcoinTestFramework):
    19+    def set_test_params(self):
    20+        self.num_nodes = 2
    21+        self.extra_args = [["-maxorphantx=1000"], ["-maxorphantx=1000", "-limitancestorcount=5"]]
    


    ajtowns commented at 9:23 am on July 8, 2019:
    You’re only ever using node 0 in this test

    TheBlueMatt commented at 7:46 pm on July 9, 2019:
    Fixed.
  24. in src/validation.cpp:624 in f1facdd3e2 outdated
    620+            // This allows protocols which rely on distrusting counterparties
    621+            // being able to broadcast descendants of an unconfirmed transaction
    622+            // to be secure by simply only having two immediately-spendable
    623+            // outputs - one for each counterparty. For more info on the uses for
    624+            // this, see https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-November/016518.html
    625+            if (nSize > 10000 || !pool.CalculateMemPoolAncestors(entry, setAncestors, 2, 1000000, nLimitDescendants + 1, nLimitDescendantSize + 10000, errString)) {
    


    ryanofsky commented at 9:16 pm on July 8, 2019:
    Can these constants be named, or at least explained? It seems like 10000 is the 40k weight limit, and 1000000 is just a big number?
  25. in test/functional/mempool_package_onemore.py:28 in f1facdd3e2 outdated
    23+    def skip_test_if_missing_module(self):
    24+        self.skip_if_no_wallet()
    25+
    26+    # Build a transaction that spends parent_txid:vout
    27+    # Return amount sent
    28+    def chain_transaction(self, node, parent_txids, vouts, value, fee, num_outputs):
    


    ryanofsky commented at 9:34 pm on July 8, 2019:
    Not great how this function and the test setup here is mostly duplicated from mempool_packages.py. Someone could clean it up later, though.
  26. in test/functional/mempool_package_onemore.py:59 in f1facdd3e2 outdated
    54+        for _ in range(4):
    55+            (txid, sent_value) = self.chain_transaction(self.nodes[0], [txid], [vout], value, fee, 2)
    56+            vout = 0
    57+            value = sent_value
    58+            chain.append([txid, value])
    59+        for _ in range(MAX_ANCESTORS - 4):
    


    ryanofsky commented at 9:51 pm on July 8, 2019:

    Having two basically identical loops just to add an extra output to the first four transactions seems like an odd choice. Maybe prefer

    0for depth in range(MAX_ANCESTORS):
    1    num_outputs = 2 if depth < 4 else 1
    2    ...
    

    TheBlueMatt commented at 7:46 pm on July 9, 2019:
    I find this more readable.
  27. in test/functional/mempool_package_onemore.py:65 in f1facdd3e2 outdated
    60+            (txid, sent_value) = self.chain_transaction(self.nodes[0], [txid], [0], value, fee, 1)
    61+            value = sent_value
    62+            chain.append([txid, value])
    63+        (second_chain, second_chain_value) = self.chain_transaction(self.nodes[0], [utxo[1]['txid']], [utxo[1]['vout']], utxo[1]['amount'], fee, 1)
    64+
    65+        # Check mempool has MAX_ANCESTORS transactions in it, and descendant and ancestor
    


    ryanofsky commented at 9:52 pm on July 8, 2019:
    Stale comment from the old test, now MAX_ANCESTORS+1
  28. in test/functional/mempool_package_onemore.py:71 in f1facdd3e2 outdated
    67+        assert_equal(len(self.nodes[0].getrawmempool(True)), MAX_ANCESTORS + 1)
    68+
    69+        # Adding one more transaction on to the chain should fail.
    70+        assert_raises_rpc_error(-26, "too-long-mempool-chain", self.chain_transaction, self.nodes[0], [txid], [0], value, fee, 1)
    71+        # ...even if it chains on from some point in the middle of the chain.
    72+        assert_raises_rpc_error(-26, "too-long-mempool-chain", self.chain_transaction, self.nodes[0], [chain[2][0]], [1], chain[2][1], fee, 1)
    


    ryanofsky commented at 9:55 pm on July 8, 2019:
    These tests would be more readable, and zip() above could be dropped if chain_transaction just took a list of txid/nout tuples

    ajtowns commented at 10:37 am on July 9, 2019:
    FWIW, I thought the way it is seemed more readable. YMMV obviously :)
  29. in test/functional/mempool_package_onemore.py:62 in f1facdd3e2 outdated
    57+            value = sent_value
    58+            chain.append([txid, value])
    59+        for _ in range(MAX_ANCESTORS - 4):
    60+            (txid, sent_value) = self.chain_transaction(self.nodes[0], [txid], [0], value, fee, 1)
    61+            value = sent_value
    62+            chain.append([txid, value])
    


    ryanofsky commented at 9:58 pm on July 8, 2019:

    Imo, tests below would be more reable if this were

    0chain.append(txid)
    1values.append(value)
    

    to get rid of all the 0/1 indexing


    jnewbery commented at 8:34 pm on July 22, 2019:
    +1, or used a namedtuple
  30. ryanofsky approved
  31. ryanofsky commented at 10:09 pm on July 8, 2019: member

    ACK f1facdd3e27d3b5c0536ab27d1f928984b8ccc25 with minimal testing. I verified new test fails without policy change and succeeds with it. I left only minor review comments which can be ignored.

    I do like ajtowns’s RBF test from #15681 (comment), and think it’d be nice if that were added.

  32. [mempool] Allow one extra single-ancestor transaction per package
    This implements the proposed policy change from [1], which allows
    certain classes of contract protocols involving revocation
    punishments to use CPFP. Note that some such use-cases may still
    want some form of one-deep package relay, though even this alone
    may greatly simplify some lightning fee negotiation.
    
    [1] https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-November/016518.html
    50cede3f5a
  33. TheBlueMatt force-pushed on Jul 9, 2019
  34. TheBlueMatt commented at 7:46 pm on July 9, 2019: member

    @ajtowns I’d prefer to not add the proposed test change, as @sdaftuar’s comment points out a critical limitation, and one I’d like to get resolved before this gets released, though not necessarily in this PR. I’d rather just fix the bug than add a test to ensure that the bug exists.

    As for general policy questions: this doesn’t result in any new transactions being accepted which violate min fee, nor does it change eviction criteria when mempool fills. What this does do, is tweak our already-somewhat-arbitrary-but-sadly-neccessary anti-DoS policies to allow one more (potentially-in-the-future) common case so that we can maximize fee revenue in the case this does get used. Thus, I don’t see any reason to need to bend over backwards to make it more restrictive, if anything, less restrictive is better.

  35. sdaftuar commented at 3:05 pm on July 12, 2019: member
    ACK f1facdd3e27d3b5c0536ab27d1f928984b8ccc25
  36. ryanofsky approved
  37. ryanofsky commented at 5:39 pm on July 15, 2019: member
    utACK 50cede3f5a4d4fbfbb7c420b94e661a6a159bced. Changes since last review: adding EXTRA_DESCENDANT_TX_SIZE_LIMIT constant, changing max ancestor size from 1,000,000 to nLimitAncestorSize constant (101,000), fixing test comment and getting rid of unused test node.
  38. ajtowns commented at 11:02 am on July 16, 2019: member

    ACK 50cede3f5a4d4fbfbb7c420b94e661a6a159bced – looked over code again, compared with previous commit, compiles, etc.

    I think this is a sufficient improvement even with the problem @sdaftuar points out:

    • if there’s no adversarial situation and you hit the descendent limit with low fee children just due to carelessness, this carveout can be used to RBF the first child (paying 25 times the feerate to account for the descendants’ fees) and make CPFP actually work in ways where you can’t do anything now
    • in the event of an adversarial situation with only two immediately spendable outputs, if you do the CPFP first, they can’t block you from RBF’ing when you need to (they can’t make use of the onemore carve out if they only have one output available – they need to use it to hit the descant limit, at which point it’s not available for onemore).
    • to DoS their channel partner, an adversary would need to be confident their partner will CPFP by too small an amount, and do their spam low-fee tx spamming before they do that. If the CPFP is a high enough amount, they’ll likely lose the fees for their spam once the mempool clears out, making that not a free attack, as well.

    It would obviously still be better to find a more general fix, but this seems to me a worthwhile improvement without introducing much of a maintenance cost.

  39. ajtowns commented at 11:12 am on July 16, 2019: member

    Patch to mempool_package_onemore.py for checking the “can RBF if I’ve added too many descendants myself” case. Maybe useful for reviewers, not suitable for inclusion since it kills the checks for the intended usecase:

     0+++ b/test/functional/mempool_package_onemore.py
     1@@ -33,7 +33,7 @@ class MempoolPackagesTest(BitcoinTestFramework):
     2         outputs = {}
     3         for i in range(num_outputs):
     4             outputs[node.getnewaddress()] = send_value
     5-        rawtx = node.createrawtransaction(inputs, outputs)
     6+        rawtx = node.createrawtransaction(inputs, outputs, 0, True)
     7         signedtx = node.signrawtransactionwithwallet(rawtx)
     8         txid = node.sendrawtransaction(signedtx['hex'])
     9         fulltx = node.getrawtransaction(txid, 1)
    10@@ -74,6 +74,12 @@ class MempoolPackagesTest(BitcoinTestFramework):
    11         assert_raises_rpc_error(-26, "too-long-mempool-chain", self.chain_transaction, self.nodes[0], [chain[0][0], second_chain], [1, 0], chain[0][1] + second_chain_value, fee, 1)
    12         # ...especially if its > 40k weight
    13         assert_raises_rpc_error(-26, "too-long-mempool-chain", self.chain_transaction, self.nodes[0], [chain[0][0]], [1], chain[0][1], fee, 350)
    14+
    15+        # can even RBF the original tx
    16+        self.chain_transaction(self.nodes[0], [chain[0][0]], [0], chain[0][1], fee*25, 10)
    17+        assert_equal(len(self.nodes[0].getrawmempool(True)), 3) # parent, second_chain, RBF'd original
    18+        return
    19+
    20         # But not if it chains directly off the first transaction
    21         self.chain_transaction(self.nodes[0], [chain[0][0]], [1], chain[0][1], fee, 1)
    22         # and the second chain should work just fine
    
  40. sdaftuar commented at 5:45 pm on July 19, 2019: member
    ACK 50cede3f5a4d4fbfbb7c420b94e661a6a159bced
  41. laanwj merged this on Jul 19, 2019
  42. laanwj closed this on Jul 19, 2019

  43. laanwj referenced this in commit 51a6e2c419 on Jul 19, 2019
  44. in src/validation.cpp:625 in 50cede3f5a
    621+            // being able to broadcast descendants of an unconfirmed transaction
    622+            // to be secure by simply only having two immediately-spendable
    623+            // outputs - one for each counterparty. For more info on the uses for
    624+            // this, see https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-November/016518.html
    625+            if (nSize >  EXTRA_DESCENDANT_TX_SIZE_LIMIT ||
    626+                    !pool.CalculateMemPoolAncestors(entry, setAncestors, 2, nLimitAncestorSize, nLimitDescendants + 1, nLimitDescendantSize + EXTRA_DESCENDANT_TX_SIZE_LIMIT, errString)) {
    


    jnewbery commented at 8:16 pm on July 22, 2019:
    Passing errString through to the second call of CalculateMemPoolAncestors() means that the error string in the CValidationState object will be incorrect because of the changed ancestor/descendant size/count parameters. Really we should declare a dummy_error_string to pass into the second call, and use the original errString in the call to state.Invalid() below.
  45. in test/functional/mempool_package_onemore.py:7 in 50cede3f5a
    0@@ -0,0 +1,86 @@
    1+#!/usr/bin/env python3
    2+# Copyright (c) 2014-2019 The Bitcoin Core developers
    3+# Distributed under the MIT software license, see the accompanying
    4+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
    5+"""Test descendant package tracking carve-out allowing one final transaction in
    6+   an otherwise-full package as long as it has only one parent and is <= 10k in
    7+   size.
    


    jnewbery commented at 8:18 pm on July 22, 2019:
    nit: virtual size (or define this in terms or transaction weight)
  46. in test/functional/mempool_package_onemore.py:46 in 50cede3f5a
    41+        return (txid, send_value)
    42+
    43+    def run_test(self):
    44+        # Mine some blocks and have them mature.
    45+        self.nodes[0].generate(101)
    46+        utxo = self.nodes[0].listunspent(10)
    


    jnewbery commented at 8:21 pm on July 22, 2019:
    nit: it’s preferable to use named transactions to make the test more readable.

    jnewbery commented at 8:23 pm on July 22, 2019:
    nit: name this variable utxos or define it as self.nodes[0].listunspent(10)[0]
  47. in test/functional/mempool_package_onemore.py:18 in 50cede3f5a
    13+from test_framework.util import assert_equal, assert_raises_rpc_error, satoshi_round
    14+
    15+MAX_ANCESTORS = 25
    16+MAX_DESCENDANTS = 25
    17+
    18+class MempoolPackagesTest(BitcoinTestFramework):
    


    jnewbery commented at 8:22 pm on July 22, 2019:
    nit: name this class MempoolPackageOnemoreTest
  48. jnewbery commented at 8:41 pm on July 22, 2019: member

    Quick code-review ACK 50cede3f5a4d4fbfbb7c420b94e661a6a159bced.

    There’s one logging bug that I think we should fix. I’ve added a bunch of nits to the test, but I agree with other reviewers that we could probably avoid a bunch of test code duplication by merging mempool_package_onemore.py with mempool_packages.py.

  49. sidhujag referenced this in commit 723330ded4 on Jul 29, 2019
  50. laanwj referenced this in commit 68da54987d on Jul 29, 2019
  51. fanquake referenced this in commit 0d20c42a01 on Sep 7, 2019
  52. ysangkok commented at 7:28 pm on November 9, 2019: none
    just FYI: a lot of interesting comments on this PR available at: https://bitcoincore.reviews/15681.html
  53. Fabcien referenced this in commit 0ea7b89e0a on Jan 8, 2021
  54. Munkybooty referenced this in commit 930fe1e94a on Nov 4, 2021
  55. Munkybooty referenced this in commit 5a699d68f1 on Nov 6, 2021
  56. Munkybooty referenced this in commit 7f8165c228 on Nov 12, 2021
  57. Munkybooty referenced this in commit 8dffdd471a on Nov 16, 2021
  58. Munkybooty referenced this in commit 507c871ed5 on Dec 16, 2021
  59. Munkybooty referenced this in commit c31713b401 on Dec 16, 2021
  60. DrahtBot locked this on Feb 15, 2022

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-22 09:12 UTC

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