From 88d747a7f71db727567f91aa0e5814873f3e8925 Mon Sep 17 00:00:00 2001 From: Richard Holland Date: Fri, 20 May 2022 09:25:41 +0000 Subject: [PATCH] hooks--NFT support --- src/ripple/app/hook/Enum.h | 1 + src/ripple/app/hook/applyHook.h | 58 ++++++++++------- src/ripple/app/hook/impl/applyHook.cpp | 86 +++++++++++++++++++++++++- 3 files changed, 123 insertions(+), 22 deletions(-) diff --git a/src/ripple/app/hook/Enum.h b/src/ripple/app/hook/Enum.h index 2bce8b306..17bab4398 100644 --- a/src/ripple/app/hook/Enum.h +++ b/src/ripple/app/hook/Enum.h @@ -30,6 +30,7 @@ namespace hook tshNONE = 0b000, tshROLLBACK = 0b001, tshCOLLECT = 0b010, + tshMIXED = 0b100, }; diff --git a/src/ripple/app/hook/applyHook.h b/src/ripple/app/hook/applyHook.h index eb592414d..295b7e462 100644 --- a/src/ripple/app/hook/applyHook.h +++ b/src/ripple/app/hook/applyHook.h @@ -39,29 +39,45 @@ namespace hook using namespace ripple; static const std::map TSHAllowances = { - {ttPAYMENT, tshROLLBACK }, - {ttESCROW_CREATE, tshROLLBACK }, - {ttESCROW_FINISH, tshROLLBACK }, - {ttACCOUNT_SET, tshNONE }, - {ttESCROW_CANCEL, tshCOLLECT }, - {ttREGULAR_KEY_SET, tshROLLBACK }, - {ttOFFER_CREATE, tshCOLLECT }, - {ttOFFER_CANCEL, tshNONE }, - {ttTICKET_CREATE, tshNONE }, - {ttSIGNER_LIST_SET, tshROLLBACK }, - {ttPAYCHAN_CREATE, tshROLLBACK }, - {ttPAYCHAN_FUND, tshCOLLECT }, - {ttPAYCHAN_CLAIM, tshCOLLECT }, - {ttCHECK_CREATE, tshROLLBACK }, - {ttCHECK_CASH, tshROLLBACK }, - {ttCHECK_CANCEL, tshCOLLECT }, - {ttDEPOSIT_PREAUTH, tshROLLBACK }, - {ttTRUST_SET, tshCOLLECT }, - {ttACCOUNT_DELETE, tshROLLBACK }, - {ttHOOK_SET, tshNONE } - // RH TODO: add NFT transactions here + {ttPAYMENT, tshROLLBACK }, + {ttESCROW_CREATE, tshROLLBACK }, + {ttESCROW_FINISH, tshROLLBACK }, + {ttACCOUNT_SET, tshNONE }, + {ttESCROW_CANCEL, tshCOLLECT }, + {ttREGULAR_KEY_SET, tshROLLBACK }, + {ttOFFER_CREATE, tshCOLLECT }, + {ttOFFER_CANCEL, tshNONE }, + {ttTICKET_CREATE, tshNONE }, + {ttSIGNER_LIST_SET, tshROLLBACK }, + {ttPAYCHAN_CREATE, tshROLLBACK }, + {ttPAYCHAN_FUND, tshCOLLECT }, + {ttPAYCHAN_CLAIM, tshCOLLECT }, + {ttCHECK_CREATE, tshROLLBACK }, + {ttCHECK_CASH, tshROLLBACK }, + {ttCHECK_CANCEL, tshCOLLECT }, + {ttDEPOSIT_PREAUTH, tshROLLBACK }, + {ttTRUST_SET, tshCOLLECT }, + {ttACCOUNT_DELETE, tshROLLBACK }, + {ttHOOK_SET, tshNONE }, + {ttNFTOKEN_MINT, tshROLLBACK }, + {ttNFTOKEN_BURN, tshCOLLECT }, + {ttNFTOKEN_CREATE_OFFER, tshROLLBACK }, + {ttNFTOKEN_CANCEL_OFFER, tshCOLLECT }, + {ttNFTOKEN_ACCEPT_OFFER, tshROLLBACK } }; +/* + ttNFTOKEN_MINT = 25, + + ttNFTOKEN_BURN = 26, + + ttNFTOKEN_CREATE_OFFER = 27, + + ttNFTOKEN_CANCEL_OFFER = 28, + + ttNFTOKEN_ACCEPT_OFFER = 29, + */ + std::vector> getTransactionalStakeHolders(STTx const& tx, ReadView const& rv); diff --git a/src/ripple/app/hook/impl/applyHook.cpp b/src/ripple/app/hook/impl/applyHook.cpp index 24181cc66..55ec6a066 100644 --- a/src/ripple/app/hook/impl/applyHook.cpp +++ b/src/ripple/app/hook/impl/applyHook.cpp @@ -21,7 +21,6 @@ using namespace ripple; namespace hook { - std::vector> getTransactionalStakeHolders(STTx const& tx, ReadView const& rv) { @@ -67,9 +66,94 @@ namespace hook }\ } + + auto const getNFTOffer = [](std::optional id, ReadView const& rv) -> + std::shared_ptr + { + if (!id) + return nullptr; + + return rv.read(keylet::nftoffer(*id)); + }; + + switch (tt) { + // NFT + case ttNFTOKEN_MINT: + { + if (tx.isFieldPresent(sfIssuer)) + ADD_TSH(tx.getAccountID(sfIssuer), canRollback); + break; + }; + + case ttNFTOKEN_BURN: + case ttNFTOKEN_CREATE_OFFER: + { + if (!tx.isFieldPresent(sfNFTokenID) || !tx.isFieldPresent(sfAccount)) + return {}; + + uint256 nid = tx.getFieldH256(sfNFTokenID); + bool hasOwner = tx.isFieldPresent(sfOwner); + AccountID owner = tx.getAccountID(hasOwner ? sfOwner : sfAccount); + + if (!nft::findToken(rv, owner, nid)) + return {}; + + auto const issuer = nft::getIssuer(nid); + + ADD_TSH(issuer, canRollback); + if (hasOwner) + ADD_TSH(owner, canRollback); + break; + } + + case ttNFTOKEN_ACCEPT_OFFER: + { + auto const bo = getNFTOffer(tx[~sfNFTokenBuyOffer], rv); + auto const so = getNFTOffer(tx[~sfNFTokenSellOffer], rv); + + if (!bo && !so) + return {}; + + if (bo) + { + ADD_TSH(bo->getAccountID(sfOwner), canRollback); + if (bo->isFieldPresent(sfDestination)) + ADD_TSH(bo->getAccountID(sfDestination), canRollback); + } + + if (so) + { + ADD_TSH(so->getAccountID(sfOwner), canRollback); + if (so->isFieldPresent(sfDestination)) + ADD_TSH(so->getAccountID(sfDestination), canRollback); + } + + break; + } + + case ttNFTOKEN_CANCEL_OFFER: + { + if (!tx.isFieldPresent(sfNFTokenOffers)) + return {}; + + auto const& offerVec = tx.getFieldV256(sfNFTokenOffers); + for (auto const& offerID : offerVec) + { + auto const offer = getNFTOffer(offerID, rv); + if (offer) + { + ADD_TSH(offer->getAccountID(sfOwner), canRollback); + if (offer->isFieldPresent(sfDestination)) + ADD_TSH(offer->getAccountID(sfDestination), canRollback); + } + } + break; + } + + // self transactions case ttACCOUNT_SET: case ttOFFER_CANCEL: