After the implementation was merged, the mailing list description was
written up as a BIP, and merged
into the BIPs repository as
The RBF policy in Bitcoin Core uses the nSequence field to signal opt-in for replaceability. According to the BIP:
This policy specifies two ways a transaction can signal that it is replaceable.
Explicit signaling: A transaction is considered to have opted in to
allowing replacement of itself if any of its inputs have an nSequence
number less than (0xffffffff - 1).
Inherited signaling: Transactions that don’t explicitly signal
replaceability are replaceable under this policy for as long as any one of
their ancestors signals replaceability and remains unconfirmed.
It was recently
that the Bitcoin Core implementation does not treat the descendants of
unconfirmed, opt-in RBF-signaling transactions as implicitly signaling
PR 21946 added code comments
to document the discrepancy between BIP125 and the implementation.
PR 22665 replaces the
bip125_replaceable field in the mempool and wallet RPC commands with a
replaceable field. The bip125_replaceable field returned whether a
transaction was replaceable according to the BIP125 rules (including through
inherited signaling), while the new replaceable field returns whether
the Bitcoin Core mempool considers the transaction replaceable.
There’s an alternative PR
22698 which implements the
inherited signaling as documented in BIP125. Which of the two approaches do you
Prior to this PR, there was a Chain interface member function
This PR changes the caller to use SignalsOptInRBF() instead. Why is
SignalsOptInRBF() a free function and not a member of the Chain
Before this PR, the bip125-replaceable field could be yes, no, or
unknown. The new replaceable field can only be true or false. Why is
it never set to unknown?
What is the IsDeprecatedRPCEnabled() function used for? Why does this
PR move that function from rpc/server to rpc/util? Describe the process
for deprecating RPC methods and fields. Why do we deprecate in this way?
Do you agree that we should use a deprecation process to change the name
from bip125-replaceable to replaceable? Why don’t we just update the
value that is returned in bip125-replaceable?
<darius27> if BIP 125 was merged, doesn't it mean it was decided at that point that that was the more desired behavior? And it seems like it was unintentional that bitcoin core did not implement this behavior. So yeah i would have thought it would make sense to implement BIP 125 instead
<raj> jnewbery, but doesn't the fact that replaceability inheritance documented in the BIP irrespective of code behavior, makes that it a more intuitive behavior? One could equally argue that the code missed a behavior which is logical?
<jnewbery> I think it's worth reviewing the discussion in https://github.com/bitcoin/bitcoin/pull/7222, which added the bip125-replaceable field to the wallet RPCs. It's a little subtle, but I think there are definitely arguments against saying that the descendant of a bip125-replaceable is itself replaceable
<michaelfolkson> From scanning that IRC conversation log I think the BIP authors just agree to write a BIP after the code has been written rather than state they will write a BIP to document what the code does
<raj> glozow, let me know if i have it wrong, if I have a descendant with RBF disables, but have one of its ancestor RBF enables, replacing that ancestor would remove the descendant from mempool. Yet when I query its RBF status, I would get false. Isn't that correct?
<raj> On BIPS: I don't thinks BIPs are (or should) be written to document code behavior. BIPS are suppose to be standards that other parts of the industry can follow knowing that it will not make any breaking behavior change. Which is violated in this case.
<jnewbery> I think it's unusual that a BIP was written for a local mempool policy. I agree that it should be documented, but a BIP doesn't seem like the right place for it. Implementers should be free to update their policy at any time, without reference to BIPs (again, those policies should be well documented)
<michaelfolkson> sipa: I think that kind of perspective cripples the value of the BIPs personally. Why bother with them? Alternative implementations should just look at Core code as the BIPs are unreliable
<jnewbery> sipa: I think "an unambigous way of referring to that idea" is more useful when the idea is probably going to be mostly fixed (ie consensus or p2p protocol). For a policy, it's much more likely that implementers will make future changes in the implementation, in which case the BIP can potentially become more harmful than useful.
<michaelfolkson> Lightning is a very different world (not one dominant implementation) but they seem to take greater care with their BOLTs and have a different perspective on what they are attempting to achieve
<jnewbery> Prior to this PR, there was a Chain interface member function isRBFOptIn(). This PR changes the caller to use SignalsOptInRBF() instead. Why is SignalsOptInRBF() a free function and not a member of the Chain interface class?
<sipa> i'm not all that happy personally about the status of BIPs; apart from consensus bips for which there is an objective determination of "in use", it seems the bip status mostly reflects whether the author took the time to update ot
<jnewbery> Which leads us nicely to the next question. What is the IsDeprecatedRPCEnabled() function used for? Why does this PR move that function from rpc/server to rpc/util? Describe the process for deprecating RPC methods and fields. Why do we deprecate in this way?
<raj> jnewbery, it checks a list of strings to find deprecated methods. If a method is found in the list, then only corresponding functions are called and results are displayed (with an warning that it has been deprecated). Which gives a nice non breaking interface for downstream users to adopt the breaking changes.
<jnewbery> ok, final question. Do you agree that we should use a deprecation process to change the name from bip125-replaceable to replaceable? Why don’t we just update the value that is returned in bip125-replaceable?
<michaelfolkson> We didn't (really) discuss the alternative PR but I think long term we go with the superior solution (assuming we can get consensus on what the superior solution is). And if that means changing the code and/or the BIP we do that
<sipa> BIP125 is a name given to an idea; bitcoin core does not implement that idea; the solution is either documenting that bitcoin core does not implement bip125, or perhaps writing another BIP that does (if people feel that idea is BIP-worthy). Under no circumstances can BIP125 be changed to suddenly mean something else