Add featureImmediateOfferKilled for tfImmediateOrCancel offers:

Fixes #4115; https://github.com/ripple/rippled/issues/4115
This commit is contained in:
Scott Schurr
2022-04-01 15:59:20 -07:00
committed by manojsdoshi
parent 7e9e9104ea
commit 649ab872ff
5 changed files with 27 additions and 12 deletions

View File

@@ -1107,6 +1107,12 @@ CreateOffer::applyGuts(Sandbox& sb, Sandbox& sbCancel)
if (bImmediateOrCancel) if (bImmediateOrCancel)
{ {
JLOG(j_.trace()) << "Immediate or cancel: offer canceled"; JLOG(j_.trace()) << "Immediate or cancel: offer canceled";
if (!crossed && sb.rules().enabled(featureImmediateOfferKilled))
// If the ImmediateOfferKilled amendment is enabled, any
// ImmediateOrCancel offer that transfers absolutely no funds
// returns tecKILLED rather than tesSUCCESS. Motivation for the
// change is here: https://github.com/ripple/rippled/issues/4115
return {tecKILLED, false};
return {tesSUCCESS, true}; return {tesSUCCESS, true};
} }

View File

@@ -74,7 +74,7 @@ namespace detail {
// Feature.cpp. Because it's only used to reserve storage, and determine how // Feature.cpp. Because it's only used to reserve storage, and determine how
// large to make the FeatureBitset, it MAY be larger. It MUST NOT be less than // large to make the FeatureBitset, it MAY be larger. It MUST NOT be less than
// the actual number of amendments. A LogicError on startup will verify this. // the actual number of amendments. A LogicError on startup will verify this.
static constexpr std::size_t numFeatures = 51; static constexpr std::size_t numFeatures = 53;
/** Amendments that this server supports and the default voting behavior. /** Amendments that this server supports and the default voting behavior.
Whether they are enabled depends on the Rules defined in the validated Whether they are enabled depends on the Rules defined in the validated
@@ -339,6 +339,7 @@ extern uint256 const fixNFTokenNegOffer;
extern uint256 const featureNonFungibleTokensV1_1; extern uint256 const featureNonFungibleTokensV1_1;
extern uint256 const fixTrustLinesToSelf; extern uint256 const fixTrustLinesToSelf;
extern uint256 const fixRemoveNFTokenAutoTrustLine; extern uint256 const fixRemoveNFTokenAutoTrustLine;
extern uint256 const featureImmediateOfferKilled;
} // namespace ripple } // namespace ripple

View File

@@ -449,6 +449,7 @@ REGISTER_FIX (fixNFTokenNegOffer, Supported::yes, DefaultVote::no)
REGISTER_FEATURE(NonFungibleTokensV1_1, Supported::yes, DefaultVote::no); REGISTER_FEATURE(NonFungibleTokensV1_1, Supported::yes, DefaultVote::no);
REGISTER_FIX (fixTrustLinesToSelf, Supported::yes, DefaultVote::no); REGISTER_FIX (fixTrustLinesToSelf, Supported::yes, DefaultVote::no);
REGISTER_FIX (fixRemoveNFTokenAutoTrustLine, Supported::yes, DefaultVote::yes); REGISTER_FIX (fixRemoveNFTokenAutoTrustLine, Supported::yes, DefaultVote::yes);
REGISTER_FEATURE(ImmediateOfferKilled, Supported::yes, DefaultVote::no);
// The following amendments have been active for at least two years. Their // The following amendments have been active for at least two years. Their
// pre-amendment code has been removed and the identifiers are deprecated. // pre-amendment code has been removed and the identifiers are deprecated.

View File

@@ -77,7 +77,7 @@ transResults()
MAKE_ERROR(tecINVARIANT_FAILED, "One or more invariants for the transaction were not satisfied."), MAKE_ERROR(tecINVARIANT_FAILED, "One or more invariants for the transaction were not satisfied."),
MAKE_ERROR(tecEXPIRED, "Expiration time is passed."), MAKE_ERROR(tecEXPIRED, "Expiration time is passed."),
MAKE_ERROR(tecDUPLICATE, "Ledger object already exists."), MAKE_ERROR(tecDUPLICATE, "Ledger object already exists."),
MAKE_ERROR(tecKILLED, "FillOrKill offer killed."), MAKE_ERROR(tecKILLED, "No funds transferred and no offer created."),
MAKE_ERROR(tecHAS_OBLIGATIONS, "The account cannot be deleted since it has obligations."), MAKE_ERROR(tecHAS_OBLIGATIONS, "The account cannot be deleted since it has obligations."),
MAKE_ERROR(tecTOO_SOON, "It is too early to attempt the requested operation. Please wait."), MAKE_ERROR(tecTOO_SOON, "It is too early to attempt the requested operation. Please wait."),
MAKE_ERROR(tecMAX_SEQUENCE_REACHED, "The maximum sequence number was reached."), MAKE_ERROR(tecMAX_SEQUENCE_REACHED, "The maximum sequence number was reached."),

View File

@@ -950,9 +950,14 @@ public:
env(pay(gw, alice, USD(1000)), ter(tesSUCCESS)); env(pay(gw, alice, USD(1000)), ter(tesSUCCESS));
// No cross: // No cross:
{
TER const expectedCode = features[featureImmediateOfferKilled]
? static_cast<TER>(tecKILLED)
: static_cast<TER>(tesSUCCESS);
env(offer(alice, XRP(1000), USD(1000)), env(offer(alice, XRP(1000), USD(1000)),
txflags(tfImmediateOrCancel), txflags(tfImmediateOrCancel),
ter(tesSUCCESS)); ter(expectedCode));
}
env.require( env.require(
balance(alice, startBalance - f - f), balance(alice, startBalance - f - f),
@@ -5165,11 +5170,12 @@ public:
FeatureBitset const flowCross{featureFlowCross}; FeatureBitset const flowCross{featureFlowCross};
FeatureBitset const takerDryOffer{fixTakerDryOfferRemoval}; FeatureBitset const takerDryOffer{fixTakerDryOfferRemoval};
FeatureBitset const rmSmallIncreasedQOffers{fixRmSmallIncreasedQOffers}; FeatureBitset const rmSmallIncreasedQOffers{fixRmSmallIncreasedQOffers};
FeatureBitset const immediateOfferKilled{featureImmediateOfferKilled};
testAll(all - takerDryOffer); testAll(all - takerDryOffer - immediateOfferKilled);
testAll(all - flowCross - takerDryOffer); testAll(all - flowCross - takerDryOffer - immediateOfferKilled);
testAll(all - flowCross); testAll(all - flowCross - immediateOfferKilled);
testAll(all - rmSmallIncreasedQOffers); testAll(all - rmSmallIncreasedQOffers - immediateOfferKilled);
testAll(all); testAll(all);
testFalseAssert(); testFalseAssert();
} }
@@ -5184,11 +5190,12 @@ class Offer_manual_test : public Offer_test
FeatureBitset const all{supported_amendments()}; FeatureBitset const all{supported_amendments()};
FeatureBitset const flowCross{featureFlowCross}; FeatureBitset const flowCross{featureFlowCross};
FeatureBitset const f1513{fix1513}; FeatureBitset const f1513{fix1513};
FeatureBitset const immediateOfferKilled{featureImmediateOfferKilled};
FeatureBitset const takerDryOffer{fixTakerDryOfferRemoval}; FeatureBitset const takerDryOffer{fixTakerDryOfferRemoval};
testAll(all - flowCross - f1513); testAll(all - flowCross - f1513 - immediateOfferKilled);
testAll(all - flowCross); testAll(all - flowCross - immediateOfferKilled);
testAll(all - f1513); testAll(all - immediateOfferKilled);
testAll(all); testAll(all);
testAll(all - flowCross - takerDryOffer); testAll(all - flowCross - takerDryOffer);