fix: Correct hybrid offer deletion on credential expiry#6843
fix: Correct hybrid offer deletion on credential expiry#6843Kassaking7 wants to merge 3 commits intoXRPLF:developfrom
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## develop #6843 +/- ##
=======================================
Coverage 81.6% 81.6%
=======================================
Files 1010 1010
Lines 75982 75974 -8
Branches 7637 7603 -34
=======================================
+ Hits 61984 61988 +4
+ Misses 13998 13986 -12
🚀 New features to boost your workflow:
|
| // Only validate domain membership when walking a domain book. | ||
| // Hybrid offers carry sfDomainID but also participate in the open | ||
| // book; expiry of the owner's domain credential should not evict | ||
| // the offer from the open book. | ||
| if (book_.domain.has_value() && entry->isFieldPresent(sfDomainID) && |
There was a problem hiding this comment.
This must be amendment gated. You can create an amendment, potentially to be bundled with other fixes
| // both offers are in the open book directory | ||
| BEAST_EXPECT(checkDirectorySize(env, openDir, 2)); | ||
|
|
||
| // this normal payment should consume the regular offer and remove the | ||
| // unfunded hybrid offer | ||
| // a regular payment crosses the hybrid offer first (FIFO, older offer), | ||
| // then stops — the regular offer is untouched. | ||
| env(pay(alice, carol, USD(5)), path(~USD), sendmax(XRP(5))); | ||
| env.close(); | ||
|
|
||
| BEAST_EXPECT(!offerExists(env, bob, hybridOfferSeq)); | ||
| BEAST_EXPECT(checkOffer(env, bob, regularOfferSeq, XRP(5), USD(5))); | ||
| BEAST_EXPECT(checkDirectorySize(env, openDir, 1)); | ||
| BEAST_EXPECT(checkOffer(env, bob, hybridOfferSeq, XRP(40), USD(40), lsfHybrid, true)); | ||
| BEAST_EXPECT(checkOffer(env, bob, regularOfferSeq, XRP(10), USD(10))); | ||
| BEAST_EXPECT(checkDirectorySize(env, openDir, 2)); |
There was a problem hiding this comment.
existing test code should not be removed. You should have an if-statements to switch expected behavior when the amendment is on/off
|
|
||
| // Regression: hybrid offer is NOT deleted from the open book when the | ||
| // owner's domain credential expires. | ||
| // | ||
| // OfferStream::step() must only run the offerInDomain eviction check | ||
| // when walking a domain book (book_.domain.has_value()). When walking | ||
| // the open book the check must be skipped so that a hybrid offer stays | ||
| // available regardless of the owner's current domain-credential status. | ||
| { |
There was a problem hiding this comment.
Let's move this to a new test function for visibility.
| // Offer still exists with 3 USD / 3 XRP remaining. | ||
| BEAST_EXPECT(checkOffer(env, devin, hybridOfferSeq, XRP(3), USD(3), lsfHybrid, true)); |
There was a problem hiding this comment.
it would be good to have to have another a domain payment trying to consume this offer after this (which should remove the offer)
| testHybridInvalidOffer(all | fixSecurity3_1_3); | ||
| testHybridOpenBookAfterCredentialExpiry(all | fixSecurity3_1_3); |
There was a problem hiding this comment.
all already includes all the amendments, you need to test all - fixSecurity3_1_3 instead
| testHybridInvalidOffer(all | fixSecurity3_1_3); | ||
| testHybridOpenBookAfterCredentialExpiry(all | fixSecurity3_1_3); |
There was a problem hiding this comment.
just curious what's the difference between testHybridInvalidOffer and testHybridOpenBookAfterCredentialExpiry? don't they test similar behaviors?
| // Hybrid offers carry sfDomainID but also participate in the open | ||
| // book; expiry of the owner's domain credential should not evict | ||
| // the offer from the open book. | ||
| if ((!view_.rules().enabled(fixSecurity3_1_3) || book_.domain.has_value()) && |
There was a problem hiding this comment.
FYI, I'm not sure if this change is within the scope of fixSecurity3_1_3, which is going to be released soon. If this isn't included, we should have a separate amendment
High Level Overview of Change
When a hybrid offer owner's domain credential expires, the offer is completely deleted from all order books (including the open book) the next time
OfferStreamencounters it. This happens becauseOfferStream::step()applies theofferInDomaincheck to ALL offers withsfDomainID, regardless of whether the current book being walked is a domain book or an open book. Hybrid offers should remain available in the open book even if the owner loses domain access.Root Cause
When
OfferStream::step()iterates through the open (non-domain) order book and encounters a hybrid offer, it runs theofferInDomaincheckContext of Change
Add a check in
OfferStream::step()to only validate domain membership when walking a domain bookAPI Impact
libxrplchange (any change that may affectlibxrplor dependents oflibxrpl)