“… used for the transactions that failed.” This is a bit vague for me, and maybe that’s okay since this is a high-level document. But let me try to describe what this actually means at a high level (without looking at the code), Pythonically:
0# Create a new package (t-sorted list of transactions) from the incoming package
1new_package = []
2for tx in package:
3 if has_parent(new_package, tx) or not feerate_okay(tx):
4 new_package.append(tx)
5fee_validate(new_package)
Consider the most trivial (and useful) case, child pays for parent. Here, parent A has a low feerate, and its child B has a high feerate, package
is [A, B]
. The first loop iteration looks at A, and asks: does A have a parent (within new_package
)? No – new_package
is empty. So then we check A’s feerate. It’s not okay, so we add A to new_package
. The second loop iteration considers B. Does it have a parent in new_package
? Yes, so add it to new_package
(no need to check its feerate). So new_package
ends up [A, B]
, so we evaluate that and it likely passes.
Let’s consider the reverse case, parent pays for child. Here, parent A has a high feerate, and B has a low feerate. Again, package
is [A, B]
. The first loop iteration finds that A does not have a parent (in new_package
), so we check A’s feerate. It is okay, so we don’t add A to the result list. The second loop checks B; it does not have a parent in new_package
, so we check its feerate. It’s not okay, so we add it to new_package
, which becomes [B]
. We check this package feerate and it fails. So parent A was not able to pay for child B, which is what we want.
Note that any package
transactions that are not in new_package
(in this second example, A) have passed their individual feerate test, so there is no need to check them again.
I think this algorithm generalizes to an arbitrary package DAG but I’m not completely sure.