mirror of
https://github.com/Xahau/xahaud.git
synced 2025-11-14 15:45:50 +00:00
Compare commits
8 Commits
litetshfix
...
fxv1-tsh
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b926e2e2f6 | ||
|
|
2876ee146d | ||
|
|
94fe1f7b29 | ||
|
|
2d93c50bcc | ||
|
|
a9f7bc81c3 | ||
|
|
10ae534300 | ||
|
|
3b353e146f | ||
|
|
7295577cdd |
@@ -45,43 +45,6 @@ public:
|
||||
};
|
||||
|
||||
using namespace ripple;
|
||||
static const std::map<uint16_t, uint8_t> 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},
|
||||
{ttNFTOKEN_MINT, tshROLLBACK},
|
||||
{ttNFTOKEN_BURN, tshCOLLECT},
|
||||
{ttNFTOKEN_CREATE_OFFER, tshROLLBACK},
|
||||
{ttNFTOKEN_CANCEL_OFFER, tshCOLLECT},
|
||||
{ttNFTOKEN_ACCEPT_OFFER, tshROLLBACK},
|
||||
{ttCLAIM_REWARD, tshROLLBACK},
|
||||
{ttINVOKE, tshROLLBACK},
|
||||
{ttURITOKEN_MINT, tshNONE},
|
||||
{ttURITOKEN_BURN, tshROLLBACK},
|
||||
{ttURITOKEN_BUY, tshROLLBACK},
|
||||
{ttURITOKEN_CREATE_SELL_OFFER, tshROLLBACK},
|
||||
{ttURITOKEN_CANCEL_SELL_OFFER, tshNONE},
|
||||
{ttIMPORT, tshROLLBACK},
|
||||
{ttGENESIS_MINT, tshCOLLECT},
|
||||
};
|
||||
|
||||
std::vector<std::pair<AccountID, bool>>
|
||||
getTransactionalStakeHolders(STTx const& tx, ReadView const& rv);
|
||||
} // namespace hook
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
using namespace ripple;
|
||||
|
||||
namespace hook {
|
||||
|
||||
using namespace ripple;
|
||||
std::vector<std::pair<AccountID, bool>>
|
||||
getTransactionalStakeHolders(STTx const& tx, ReadView const& rv)
|
||||
{
|
||||
@@ -38,19 +40,10 @@ getTransactionalStakeHolders(STTx const& tx, ReadView const& rv)
|
||||
|
||||
uint16_t tt = tx.getFieldU16(sfTransactionType);
|
||||
|
||||
uint8_t tsh = tshNONE;
|
||||
if (auto const& found = hook::TSHAllowances.find(tt);
|
||||
found != hook::TSHAllowances.end())
|
||||
tsh = found->second;
|
||||
else
|
||||
return {};
|
||||
|
||||
std::map<AccountID, std::pair<int, bool>> tshEntries;
|
||||
|
||||
int upto = 0;
|
||||
|
||||
bool canRollback = tsh & tshROLLBACK;
|
||||
|
||||
auto const ADD_TSH = [&otxnAcc, &tshEntries, &upto](
|
||||
const AccountID& acc_r, bool rb) {
|
||||
if (acc_r != *otxnAcc)
|
||||
@@ -71,11 +64,14 @@ getTransactionalStakeHolders(STTx const& tx, ReadView const& rv)
|
||||
return rv.read(keylet::nftoffer(*id));
|
||||
};
|
||||
|
||||
bool const tshSTRONG = true; // tshROLLBACK
|
||||
bool const tshWEAK = false; // tshCOLLECT
|
||||
|
||||
switch (tt)
|
||||
{
|
||||
case ttIMPORT: {
|
||||
if (tx.isFieldPresent(sfIssuer))
|
||||
ADD_TSH(tx.getAccountID(sfIssuer), canRollback);
|
||||
ADD_TSH(tx.getAccountID(sfIssuer), tshSTRONG);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -103,13 +99,13 @@ getTransactionalStakeHolders(STTx const& tx, ReadView const& rv)
|
||||
else if (*otxnAcc == owner)
|
||||
{
|
||||
// the owner burns their token, and the issuer is a weak TSH
|
||||
ADD_TSH(issuer, canRollback);
|
||||
ADD_TSH(issuer, tshWEAK);
|
||||
}
|
||||
else
|
||||
{
|
||||
// the issuer burns the owner's token, and the owner is a weak
|
||||
// TSH
|
||||
ADD_TSH(owner, canRollback);
|
||||
ADD_TSH(owner, tshWEAK);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -126,16 +122,16 @@ getTransactionalStakeHolders(STTx const& tx, ReadView const& rv)
|
||||
|
||||
auto const owner = ut->getAccountID(sfOwner);
|
||||
|
||||
if (owner != tx.getAccountID(sfAccount))
|
||||
if (owner != *otxnAcc)
|
||||
{
|
||||
// current owner is a strong TSH
|
||||
ADD_TSH(owner, canRollback);
|
||||
// current owner is a TSH
|
||||
ADD_TSH(owner, tshSTRONG);
|
||||
}
|
||||
|
||||
// issuer is also a strong TSH if the burnable flag is set
|
||||
// issuer is also a TSH if the burnable flag is set
|
||||
auto const issuer = ut->getAccountID(sfIssuer);
|
||||
if (issuer != owner)
|
||||
ADD_TSH(issuer, ut->getFlags() & lsfBurnable);
|
||||
ADD_TSH(issuer, (ut->getFlags() & lsfBurnable) ? tshSTRONG : tshWEAK);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -154,22 +150,30 @@ getTransactionalStakeHolders(STTx const& tx, ReadView const& rv)
|
||||
|
||||
// issuer is a strong TSH if the burnable flag is set
|
||||
if (issuer != owner)
|
||||
ADD_TSH(issuer, ut->getFlags() & lsfBurnable);
|
||||
ADD_TSH(issuer, (ut->getFlags() & lsfBurnable) ? tshSTRONG : tshWEAK);
|
||||
|
||||
// destination is a strong tsh
|
||||
if (tx.isFieldPresent(sfDestination))
|
||||
ADD_TSH(tx.getAccountID(sfDestination), canRollback);
|
||||
ADD_TSH(tx.getAccountID(sfDestination), tshSTRONG);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// NFT
|
||||
case ttNFTOKEN_MINT:
|
||||
case ttCLAIM_REWARD: {
|
||||
if (tx.isFieldPresent(sfIssuer))
|
||||
ADD_TSH(tx.getAccountID(sfIssuer), canRollback);
|
||||
case ttURITOKEN_CANCEL_SELL_OFFER: {
|
||||
Keylet const id{ltURI_TOKEN, tx.getFieldH256(sfURITokenID)};
|
||||
if (!rv.exists(id))
|
||||
return {};
|
||||
|
||||
auto const ut = rv.read(id);
|
||||
if (!ut || ut->getFieldU16(sfLedgerEntryType) != ltURI_TOKEN)
|
||||
return {};
|
||||
|
||||
// destination is weak tsh
|
||||
if (ut->isFieldPresent(sfDestination))
|
||||
ADD_TSH(ut->getAccountID(sfDestination), tshWEAK);
|
||||
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
case ttNFTOKEN_BURN:
|
||||
case ttNFTOKEN_CREATE_OFFER: {
|
||||
@@ -190,7 +194,7 @@ getTransactionalStakeHolders(STTx const& tx, ReadView const& rv)
|
||||
|
||||
ADD_TSH(issuer, issuerCanRollback);
|
||||
if (hasOwner)
|
||||
ADD_TSH(owner, canRollback);
|
||||
ADD_TSH(owner, tshWEAK);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -209,16 +213,16 @@ getTransactionalStakeHolders(STTx const& tx, ReadView const& rv)
|
||||
|
||||
if (bo)
|
||||
{
|
||||
ADD_TSH(bo->getAccountID(sfOwner), canRollback);
|
||||
ADD_TSH(bo->getAccountID(sfOwner), tshSTRONG);
|
||||
if (bo->isFieldPresent(sfDestination))
|
||||
ADD_TSH(bo->getAccountID(sfDestination), canRollback);
|
||||
ADD_TSH(bo->getAccountID(sfDestination), tshSTRONG);
|
||||
}
|
||||
|
||||
if (so)
|
||||
{
|
||||
ADD_TSH(so->getAccountID(sfOwner), canRollback);
|
||||
ADD_TSH(so->getAccountID(sfOwner), tshSTRONG);
|
||||
if (so->isFieldPresent(sfDestination))
|
||||
ADD_TSH(so->getAccountID(sfDestination), canRollback);
|
||||
ADD_TSH(so->getAccountID(sfDestination), tshSTRONG);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -234,10 +238,10 @@ getTransactionalStakeHolders(STTx const& tx, ReadView const& rv)
|
||||
auto const offer = getNFTOffer(offerID, rv);
|
||||
if (offer)
|
||||
{
|
||||
ADD_TSH(offer->getAccountID(sfOwner), canRollback);
|
||||
ADD_TSH(offer->getAccountID(sfOwner), tshWEAK);
|
||||
if (offer->isFieldPresent(sfDestination))
|
||||
ADD_TSH(
|
||||
offer->getAccountID(sfDestination), canRollback);
|
||||
offer->getAccountID(sfDestination), tshWEAK);
|
||||
|
||||
// issuer can't stop people canceling their offers, but can
|
||||
// get weak executions
|
||||
@@ -249,9 +253,14 @@ getTransactionalStakeHolders(STTx const& tx, ReadView const& rv)
|
||||
break;
|
||||
}
|
||||
|
||||
case ttNFTOKEN_MINT:
|
||||
case ttCLAIM_REWARD: {
|
||||
if (tx.isFieldPresent(sfIssuer))
|
||||
ADD_TSH(tx.getAccountID(sfIssuer), tshSTRONG);
|
||||
break;
|
||||
};
|
||||
|
||||
// self transactions
|
||||
case ttURITOKEN_MINT:
|
||||
case ttURITOKEN_CANCEL_SELL_OFFER:
|
||||
case ttACCOUNT_SET:
|
||||
case ttOFFER_CANCEL:
|
||||
case ttTICKET_CREATE:
|
||||
@@ -264,18 +273,19 @@ getTransactionalStakeHolders(STTx const& tx, ReadView const& rv)
|
||||
case ttREGULAR_KEY_SET: {
|
||||
if (!tx.isFieldPresent(sfRegularKey))
|
||||
return {};
|
||||
ADD_TSH(tx.getAccountID(sfRegularKey), canRollback);
|
||||
ADD_TSH(tx.getAccountID(sfRegularKey), tshSTRONG);
|
||||
break;
|
||||
}
|
||||
|
||||
case ttDEPOSIT_PREAUTH: {
|
||||
if (!tx.isFieldPresent(sfAuthorize))
|
||||
return {};
|
||||
ADD_TSH(tx.getAccountID(sfAuthorize), canRollback);
|
||||
ADD_TSH(tx.getAccountID(sfAuthorize), tshSTRONG);
|
||||
break;
|
||||
}
|
||||
|
||||
// simple two party transactions
|
||||
case ttURITOKEN_MINT:
|
||||
case ttPAYMENT:
|
||||
case ttESCROW_CREATE:
|
||||
case ttCHECK_CREATE:
|
||||
@@ -283,7 +293,7 @@ getTransactionalStakeHolders(STTx const& tx, ReadView const& rv)
|
||||
case ttPAYCHAN_CREATE:
|
||||
case ttINVOKE: {
|
||||
if (destAcc)
|
||||
ADD_TSH(*destAcc, canRollback);
|
||||
ADD_TSH(*destAcc, tshSTRONG);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -294,24 +304,32 @@ getTransactionalStakeHolders(STTx const& tx, ReadView const& rv)
|
||||
auto const& lim = tx.getFieldAmount(sfLimitAmount);
|
||||
AccountID const& issuer = lim.getIssuer();
|
||||
|
||||
ADD_TSH(issuer, canRollback);
|
||||
ADD_TSH(issuer, tshWEAK);
|
||||
break;
|
||||
}
|
||||
|
||||
case ttESCROW_CANCEL:
|
||||
case ttESCROW_FINISH: {
|
||||
if (!tx.isFieldPresent(sfOwner) ||
|
||||
!tx.isFieldPresent(sfOfferSequence))
|
||||
if (!tx.isFieldPresent(sfOwner))
|
||||
return {};
|
||||
|
||||
auto escrow = rv.read(keylet::escrow(
|
||||
tx.getAccountID(sfOwner), tx.getFieldU32(sfOfferSequence)));
|
||||
if (!tx.isFieldPresent(sfOfferSequence) &&
|
||||
!tx.isFieldPresent(sfEscrowID))
|
||||
return {};
|
||||
|
||||
std::optional<uint256> escrowID = tx[~sfEscrowID];
|
||||
std::optional<std::uint32_t> offerSeq = tx[~sfOfferSequence];
|
||||
|
||||
Keylet k = escrowID
|
||||
? Keylet(ltESCROW, *escrowID)
|
||||
: keylet::escrow(tx.getAccountID(sfOwner), *offerSeq);
|
||||
|
||||
auto escrow = rv.read(k);
|
||||
if (!escrow)
|
||||
return {};
|
||||
|
||||
ADD_TSH(escrow->getAccountID(sfAccount), true);
|
||||
ADD_TSH(escrow->getAccountID(sfDestination), canRollback);
|
||||
ADD_TSH(escrow->getAccountID(sfAccount), tshWEAK);
|
||||
ADD_TSH(escrow->getAccountID(sfDestination), tshWEAK);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -324,8 +342,8 @@ getTransactionalStakeHolders(STTx const& tx, ReadView const& rv)
|
||||
if (!chan)
|
||||
return {};
|
||||
|
||||
ADD_TSH(chan->getAccountID(sfAccount), true);
|
||||
ADD_TSH(chan->getAccountID(sfDestination), canRollback);
|
||||
ADD_TSH(chan->getAccountID(sfAccount), tshWEAK);
|
||||
ADD_TSH(chan->getAccountID(sfDestination), tshWEAK);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -338,8 +356,8 @@ getTransactionalStakeHolders(STTx const& tx, ReadView const& rv)
|
||||
if (!check)
|
||||
return {};
|
||||
|
||||
ADD_TSH(check->getAccountID(sfAccount), true);
|
||||
ADD_TSH(check->getAccountID(sfDestination), canRollback);
|
||||
ADD_TSH(check->getAccountID(sfAccount), tshWEAK);
|
||||
ADD_TSH(check->getAccountID(sfDestination), tshWEAK);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -349,7 +367,7 @@ getTransactionalStakeHolders(STTx const& tx, ReadView const& rv)
|
||||
STArray const& signerEntries = tx.getFieldArray(sfSignerEntries);
|
||||
for (auto const& entryObj : signerEntries)
|
||||
if (entryObj.isFieldPresent(sfAccount))
|
||||
ADD_TSH(entryObj.getAccountID(sfAccount), canRollback);
|
||||
ADD_TSH(entryObj.getAccountID(sfAccount), tshSTRONG);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -361,7 +379,7 @@ getTransactionalStakeHolders(STTx const& tx, ReadView const& rv)
|
||||
{
|
||||
if (mint.isFieldPresent(sfDestination))
|
||||
{
|
||||
ADD_TSH(mint.getAccountID(sfDestination), canRollback);
|
||||
ADD_TSH(mint.getAccountID(sfDestination), tshWEAK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1437,15 +1437,13 @@ Transactor::addWeakTSHFromSandbox(detail::ApplyViewBase const& pv)
|
||||
TER
|
||||
Transactor::doTSH(
|
||||
bool strong, // only strong iff true, only weak iff false
|
||||
std::vector<std::pair<AccountID, bool>> tsh,
|
||||
hook::HookStateMap& stateMap,
|
||||
std::vector<hook::HookResult>& results,
|
||||
std::shared_ptr<STObject const> const& provisionalMeta)
|
||||
{
|
||||
auto& view = ctx_.view();
|
||||
|
||||
std::vector<std::pair<AccountID, bool>> tsh =
|
||||
hook::getTransactionalStakeHolders(ctx_.tx, view);
|
||||
|
||||
// add the extra TSH marked out by the specific transactor (if applicable)
|
||||
if (!strong)
|
||||
for (auto& weakTsh : additionalWeakTSH_)
|
||||
@@ -1463,22 +1461,37 @@ Transactor::doTSH(
|
||||
// obviously we will never execute OTXN account
|
||||
// as a TSH because they already had first execution
|
||||
if (tshAccountID == account_)
|
||||
{
|
||||
JLOG(j_.trace()) << "doTSH: tshAccountID == account_";
|
||||
continue;
|
||||
}
|
||||
|
||||
if (alreadyProcessed.find(tshAccountID) != alreadyProcessed.end())
|
||||
{
|
||||
JLOG(j_.trace()) << "doTSH: alreadyProcessed.find(tshAccountID) != "
|
||||
"alreadyProcessed.end()";
|
||||
continue;
|
||||
}
|
||||
|
||||
alreadyProcessed.emplace(tshAccountID);
|
||||
|
||||
// only process the relevant ones
|
||||
if ((!canRollback && strong) || (canRollback && !strong))
|
||||
{
|
||||
JLOG(j_.trace()) << "doTSH: (!canRollback && strong) || "
|
||||
"(canRollback && !strong)";
|
||||
continue;
|
||||
}
|
||||
|
||||
auto klTshHook = keylet::hook(tshAccountID);
|
||||
|
||||
auto tshHook = view.read(klTshHook);
|
||||
if (!(tshHook && tshHook->isFieldPresent(sfHooks)))
|
||||
{
|
||||
JLOG(j_.trace())
|
||||
<< "doTSH: !(tshHook && tshHook->isFieldPresent(sfHooks))";
|
||||
continue;
|
||||
}
|
||||
|
||||
// scoping here allows tshAcc to leave scope before
|
||||
// hook execution, which is probably safer
|
||||
@@ -1486,7 +1499,10 @@ Transactor::doTSH(
|
||||
// check if the TSH exists and/or has any hooks
|
||||
auto tshAcc = view.peek(keylet::account(tshAccountID));
|
||||
if (!tshAcc)
|
||||
{
|
||||
JLOG(j_.trace()) << "doTSH: !tshAcc";
|
||||
continue;
|
||||
}
|
||||
|
||||
// compute and deduct fees for the TSH if applicable
|
||||
XRPAmount tshFeeDrops =
|
||||
@@ -1494,7 +1510,10 @@ Transactor::doTSH(
|
||||
|
||||
// no hooks to execute, skip tsh
|
||||
if (tshFeeDrops == 0)
|
||||
{
|
||||
JLOG(j_.trace()) << "doTSH: tshFeeDrops == 0";
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(tshFeeDrops >= beast::zero);
|
||||
|
||||
@@ -1698,6 +1717,9 @@ Transactor::operator()()
|
||||
// application to the ledger
|
||||
std::map<AccountID, std::set<uint256>> aawMap;
|
||||
|
||||
std::vector<std::pair<AccountID, bool>> tsh =
|
||||
hook::getTransactionalStakeHolders(ctx_.tx, ctx_.view());
|
||||
|
||||
// Pre-application (Strong TSH) Hooks are executed here
|
||||
// These TSH have the right to rollback.
|
||||
// Weak TSH and callback are executed post-application.
|
||||
@@ -1726,7 +1748,7 @@ Transactor::operator()()
|
||||
// (who have the right to rollback the txn), any weak TSH will be
|
||||
// executed after doApply has been successful (callback as well)
|
||||
|
||||
result = doTSH(true, stateMap, hookResults, {});
|
||||
result = doTSH(true, tsh, stateMap, hookResults, {});
|
||||
}
|
||||
|
||||
// write state if all chains executed successfully
|
||||
@@ -1969,7 +1991,7 @@ Transactor::operator()()
|
||||
hook::HookStateMap stateMap;
|
||||
std::vector<hook::HookResult> weakResults;
|
||||
|
||||
doTSH(false, stateMap, weakResults, proMeta);
|
||||
doTSH(false, tsh, stateMap, weakResults, proMeta);
|
||||
|
||||
// execute any hooks that nominated for 'again as weak'
|
||||
for (auto const& [accID, hookHashes] : aawMap)
|
||||
|
||||
@@ -188,6 +188,7 @@ protected:
|
||||
TER
|
||||
doTSH(
|
||||
bool strong, // only do strong TSH iff true, otheriwse only weak
|
||||
std::vector<std::pair<AccountID, bool>> tsh,
|
||||
hook::HookStateMap& stateMap,
|
||||
std::vector<hook::HookResult>& result,
|
||||
std::shared_ptr<STObject const> const& provisionalMeta);
|
||||
|
||||
@@ -223,11 +223,11 @@ private:
|
||||
}
|
||||
|
||||
// Check
|
||||
// | otxn | tsh | cancel | create | cash |
|
||||
// | A | A | S | S | N |
|
||||
// | A | D | N | S | N |
|
||||
// | D | D | S | N | S |
|
||||
// | D | A | S | N | S |
|
||||
// | otxn | tsh | cancel | cash | create |
|
||||
// | A | A | S | N | S |
|
||||
// | A | D | W | N | S |
|
||||
// | D | D | S | S | N |
|
||||
// | D | A | W | W | N |
|
||||
static uint256
|
||||
getCheckIndex(AccountID const& account, std::uint32_t uSequence)
|
||||
{
|
||||
@@ -285,7 +285,7 @@ private:
|
||||
|
||||
// otxn: account
|
||||
// tsh destination
|
||||
// w/s: none
|
||||
// w/s: weak
|
||||
{
|
||||
test::jtx::Env env{
|
||||
*this,
|
||||
@@ -323,7 +323,9 @@ private:
|
||||
auto const jrr = env.rpc("json", "tx", to_string(params));
|
||||
auto const meta = jrr[jss::result][jss::meta];
|
||||
auto const executions = meta[sfHookExecutions.jsonName];
|
||||
BEAST_EXPECT(executions.size() == 0);
|
||||
auto const execution = executions[0u][sfHookExecution.jsonName];
|
||||
BEAST_EXPECT(execution[sfHookResult.jsonName] == 3);
|
||||
BEAST_EXPECT(execution[sfHookReturnString.jsonName] == "00000001");
|
||||
}
|
||||
|
||||
// otxn: dest
|
||||
@@ -369,7 +371,7 @@ private:
|
||||
|
||||
// otxn: dest
|
||||
// tsh account
|
||||
// w/s: strong
|
||||
// w/s: weak
|
||||
{
|
||||
test::jtx::Env env{
|
||||
*this,
|
||||
@@ -381,13 +383,17 @@ private:
|
||||
env.fund(XRP(1000), account, dest);
|
||||
env.close();
|
||||
|
||||
// set tsh collect
|
||||
env(fset(account, asfTshCollect));
|
||||
env.close();
|
||||
|
||||
// create check
|
||||
uint256 const checkId{getCheckIndex(account, env.seq(account))};
|
||||
env(check::create(account, dest, XRP(100)), ter(tesSUCCESS));
|
||||
env.close();
|
||||
|
||||
// set tsh hook
|
||||
env(hook(account, {{hso(TshHook, overrideFlag)}}, 0),
|
||||
env(hook(account, {{hso(TshHook, collectFlag)}}, 0),
|
||||
fee(XRP(1)),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
@@ -405,7 +411,7 @@ private:
|
||||
auto const executions = meta[sfHookExecutions.jsonName];
|
||||
auto const execution = executions[0u][sfHookExecution.jsonName];
|
||||
BEAST_EXPECT(execution[sfHookResult.jsonName] == 3);
|
||||
BEAST_EXPECT(execution[sfHookReturnString.jsonName] == "00000000");
|
||||
BEAST_EXPECT(execution[sfHookReturnString.jsonName] == "00000001");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -462,7 +468,7 @@ private:
|
||||
|
||||
// otxn: dest
|
||||
// tsh account
|
||||
// w/s: strong
|
||||
// w/s: weak
|
||||
{
|
||||
test::jtx::Env env{
|
||||
*this,
|
||||
@@ -504,7 +510,7 @@ private:
|
||||
auto const executions = meta[sfHookExecutions.jsonName];
|
||||
auto const execution = executions[0u][sfHookExecution.jsonName];
|
||||
BEAST_EXPECT(execution[sfHookResult.jsonName] == 3);
|
||||
BEAST_EXPECT(execution[sfHookReturnString.jsonName] == "00000000");
|
||||
BEAST_EXPECT(execution[sfHookReturnString.jsonName] == "00000001");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -782,7 +788,7 @@ private:
|
||||
// | A | A | S | S | S |
|
||||
// | A | D | W | S | W |
|
||||
// | D | D | S | N | S |
|
||||
// | D | A | S | N | S |
|
||||
// | D | A | W | N | S |
|
||||
|
||||
static uint256
|
||||
getEscrowIndex(AccountID const& account, std::uint32_t uSequence)
|
||||
@@ -898,7 +904,9 @@ private:
|
||||
auto const jrr = env.rpc("json", "tx", to_string(params));
|
||||
auto const meta = jrr[jss::result][jss::meta];
|
||||
auto const executions = meta[sfHookExecutions.jsonName];
|
||||
BEAST_EXPECT(executions.size() == 0);
|
||||
auto const execution = executions[0u][sfHookExecution.jsonName];
|
||||
BEAST_EXPECT(execution[sfHookResult.jsonName] == 3);
|
||||
BEAST_EXPECT(execution[sfHookReturnString.jsonName] == "00000001");
|
||||
}
|
||||
|
||||
// otxn: dest
|
||||
@@ -953,7 +961,7 @@ private:
|
||||
|
||||
// otxn: dest
|
||||
// tsh account
|
||||
// w/s: strong
|
||||
// w/s: weak
|
||||
{
|
||||
test::jtx::Env env{
|
||||
*this,
|
||||
@@ -1002,7 +1010,7 @@ private:
|
||||
auto const executions = meta[sfHookExecutions.jsonName];
|
||||
auto const execution = executions[0u][sfHookExecution.jsonName];
|
||||
BEAST_EXPECT(execution[sfHookResult.jsonName] == 3);
|
||||
BEAST_EXPECT(execution[sfHookReturnString.jsonName] == "00000000");
|
||||
BEAST_EXPECT(execution[sfHookReturnString.jsonName] == "00000001");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1129,11 +1137,9 @@ private:
|
||||
auto const jrr = env.rpc("json", "tx", to_string(params));
|
||||
auto const meta = jrr[jss::result][jss::meta];
|
||||
auto const executions = meta[sfHookExecutions.jsonName];
|
||||
BEAST_EXPECT(executions.size() == 0);
|
||||
// auto const execution = executions[0u][sfHookExecution.jsonName];
|
||||
// BEAST_EXPECT(execution[sfHookResult.jsonName] == 3);
|
||||
// BEAST_EXPECT(execution[sfHookReturnString.jsonName] ==
|
||||
// "00000001");
|
||||
auto const execution = executions[0u][sfHookExecution.jsonName];
|
||||
BEAST_EXPECT(execution[sfHookResult.jsonName] == 3);
|
||||
BEAST_EXPECT(execution[sfHookReturnString.jsonName] == "00000001");
|
||||
}
|
||||
|
||||
// otxn: dest
|
||||
@@ -1249,7 +1255,9 @@ private:
|
||||
auto const jrr = env.rpc("json", "tx", to_string(params));
|
||||
auto const meta = jrr[jss::result][jss::meta];
|
||||
auto const executions = meta[sfHookExecutions.jsonName];
|
||||
BEAST_EXPECT(executions.size() == 0);
|
||||
auto const execution = executions[0u][sfHookExecution.jsonName];
|
||||
BEAST_EXPECT(execution[sfHookResult.jsonName] == 3);
|
||||
BEAST_EXPECT(execution[sfHookReturnString.jsonName] == "00000001");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1407,7 +1415,7 @@ private:
|
||||
|
||||
// otxn: account
|
||||
// tsh dest
|
||||
// w/s: strong
|
||||
// w/s: weak
|
||||
{
|
||||
test::jtx::Env env{
|
||||
*this,
|
||||
@@ -1420,8 +1428,8 @@ private:
|
||||
env.close();
|
||||
|
||||
// set tsh collect
|
||||
// env(fset(dest, asfTshCollect));
|
||||
// env.close();
|
||||
env(fset(dest, asfTshCollect));
|
||||
env.close();
|
||||
|
||||
// create escrow
|
||||
auto const seq1 = env.seq(account);
|
||||
@@ -1433,7 +1441,7 @@ private:
|
||||
env.close();
|
||||
|
||||
// set tsh hook
|
||||
env(hook(dest, {{hso(TshHook, overrideFlag)}}, 0),
|
||||
env(hook(dest, {{hso(TshHook, collectFlag)}}, 0),
|
||||
fee(XRP(1)),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
@@ -1453,7 +1461,7 @@ private:
|
||||
auto const executions = meta[sfHookExecutions.jsonName];
|
||||
auto const execution = executions[0u][sfHookExecution.jsonName];
|
||||
BEAST_EXPECT(execution[sfHookResult.jsonName] == 3);
|
||||
BEAST_EXPECT(execution[sfHookReturnString.jsonName] == "00000000");
|
||||
BEAST_EXPECT(execution[sfHookReturnString.jsonName] == "00000001");
|
||||
}
|
||||
|
||||
// otxn: dest
|
||||
@@ -1505,7 +1513,7 @@ private:
|
||||
|
||||
// otxn: dest
|
||||
// tsh account
|
||||
// w/s: strong
|
||||
// w/s: weak
|
||||
{
|
||||
test::jtx::Env env{
|
||||
*this,
|
||||
@@ -1517,6 +1525,10 @@ private:
|
||||
env.fund(XRP(1000), account, dest);
|
||||
env.close();
|
||||
|
||||
// set tsh collect
|
||||
env(fset(account, asfTshCollect));
|
||||
env.close();
|
||||
|
||||
// create escrow
|
||||
auto const seq1 = env.seq(account);
|
||||
NetClock::time_point const finishTime = env.now() + 1s;
|
||||
@@ -1527,7 +1539,7 @@ private:
|
||||
env.close();
|
||||
|
||||
// set tsh hook
|
||||
env(hook(account, {{hso(TshHook, overrideFlag)}}, 0),
|
||||
env(hook(account, {{hso(TshHook, collectFlag)}}, 0),
|
||||
fee(XRP(1)),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
@@ -1547,7 +1559,7 @@ private:
|
||||
auto const executions = meta[sfHookExecutions.jsonName];
|
||||
auto const execution = executions[0u][sfHookExecution.jsonName];
|
||||
BEAST_EXPECT(execution[sfHookResult.jsonName] == 3);
|
||||
BEAST_EXPECT(execution[sfHookReturnString.jsonName] == "00000000");
|
||||
BEAST_EXPECT(execution[sfHookReturnString.jsonName] == "00000001");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1569,6 +1581,11 @@ private:
|
||||
network::makeNetworkConfig(21337, "10", "1000000", "200000"),
|
||||
features};
|
||||
|
||||
// Env env{*this, envconfig(), features, nullptr,
|
||||
// // beast::severities::kWarning
|
||||
// beast::severities::kTrace
|
||||
// };
|
||||
|
||||
auto const account = Account("alice");
|
||||
auto const dest = Account("bob");
|
||||
env.fund(XRP(1000), account, dest);
|
||||
@@ -1667,7 +1684,9 @@ private:
|
||||
auto const jrr = env.rpc("json", "tx", to_string(params));
|
||||
auto const meta = jrr[jss::result][jss::meta];
|
||||
auto const executions = meta[sfHookExecutions.jsonName];
|
||||
BEAST_EXPECT(executions.size() == 0);
|
||||
auto const execution = executions[0u][sfHookExecution.jsonName];
|
||||
BEAST_EXPECT(execution[sfHookResult.jsonName] == 3);
|
||||
BEAST_EXPECT(execution[sfHookReturnString.jsonName] == "00000001");
|
||||
}
|
||||
|
||||
// otxn: dest
|
||||
@@ -1777,7 +1796,9 @@ private:
|
||||
auto const jrr = env.rpc("json", "tx", to_string(params));
|
||||
auto const meta = jrr[jss::result][jss::meta];
|
||||
auto const executions = meta[sfHookExecutions.jsonName];
|
||||
BEAST_EXPECT(executions.size() == 0);
|
||||
auto const execution = executions[0u][sfHookExecution.jsonName];
|
||||
BEAST_EXPECT(execution[sfHookResult.jsonName] == 3);
|
||||
BEAST_EXPECT(execution[sfHookReturnString.jsonName] == "00000001");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2187,7 +2208,7 @@ private:
|
||||
// Offer
|
||||
// | otxn | tsh | cancel | create |
|
||||
// | A | A | S | S |
|
||||
// | A | C | N | N |
|
||||
// | A | C | N | W |
|
||||
|
||||
void
|
||||
testOfferCancelTSH(FeatureBitset features)
|
||||
@@ -2309,13 +2330,15 @@ private:
|
||||
auto const gw = Account{"gateway"};
|
||||
auto const USD = gw["USD"];
|
||||
env.fund(XRP(1000), account, cross, gw);
|
||||
env.trust(USD(10000), cross);
|
||||
env(pay(gw, cross, USD(1000)));
|
||||
env.close();
|
||||
|
||||
// set tsh collect
|
||||
env(fset(cross, asfTshCollect));
|
||||
|
||||
// gw create offer
|
||||
env(offer(gw, USD(1000), XRP(1000)));
|
||||
// cross create offer
|
||||
env(offer(cross, XRP(1000), USD(1000)));
|
||||
env.close();
|
||||
|
||||
// set tsh hook
|
||||
@@ -2337,7 +2360,9 @@ private:
|
||||
auto const jrr = env.rpc("json", "tx", to_string(params));
|
||||
auto const meta = jrr[jss::result][jss::meta];
|
||||
auto const executions = meta[sfHookExecutions.jsonName];
|
||||
BEAST_EXPECT(executions.size() == 0);
|
||||
auto const execution = executions[0u][sfHookExecution.jsonName];
|
||||
BEAST_EXPECT(execution[sfHookResult.jsonName] == 3);
|
||||
BEAST_EXPECT(execution[sfHookReturnString.jsonName] == "00000001");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2482,7 +2507,7 @@ private:
|
||||
// | A | A | S | S | S |
|
||||
// | A | D | W | S | W |
|
||||
// | D | D | S | N | N |
|
||||
// | D | A | S | N | N |
|
||||
// | D | A | W | N | N |
|
||||
|
||||
static uint256
|
||||
channel(
|
||||
@@ -2548,6 +2573,7 @@ private:
|
||||
|
||||
// claim paychannel
|
||||
env(paychan::claim(account, chan, reqBal, authAmt),
|
||||
txflags(tfClose),
|
||||
fee(XRP(1)),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
@@ -2601,6 +2627,7 @@ private:
|
||||
|
||||
// claim paychannel
|
||||
env(paychan::claim(account, chan, reqBal, authAmt),
|
||||
txflags(tfClose),
|
||||
fee(XRP(1)),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
@@ -2654,6 +2681,7 @@ private:
|
||||
signClaimAuth(account.pk(), account.sk(), chan, authAmt);
|
||||
env(paychan::claim(
|
||||
dest, chan, reqBal, authAmt, Slice(sig), account.pk()),
|
||||
txflags(tfClose),
|
||||
fee(XRP(1)),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
@@ -2672,7 +2700,7 @@ private:
|
||||
|
||||
// otxn: dest
|
||||
// tsh account
|
||||
// w/s: strong
|
||||
// w/s: weak
|
||||
{
|
||||
test::jtx::Env env{
|
||||
*this,
|
||||
@@ -2684,6 +2712,9 @@ private:
|
||||
env.fund(XRP(1000), account, dest);
|
||||
env.close();
|
||||
|
||||
// set tsh collect
|
||||
env(fset(account, asfTshCollect));
|
||||
|
||||
// create paychannel
|
||||
auto const pk = account.pk();
|
||||
auto const settleDelay = 100s;
|
||||
@@ -2693,7 +2724,7 @@ private:
|
||||
env.close();
|
||||
|
||||
// set tsh hook
|
||||
env(hook(account, {{hso(TshHook, overrideFlag)}}, 0),
|
||||
env(hook(account, {{hso(TshHook, collectFlag)}}, 0),
|
||||
fee(XRP(1)),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
@@ -2707,6 +2738,7 @@ private:
|
||||
signClaimAuth(account.pk(), account.sk(), chan, authAmt);
|
||||
env(paychan::claim(
|
||||
dest, chan, reqBal, authAmt, Slice(sig), account.pk()),
|
||||
txflags(tfClose),
|
||||
fee(XRP(1)),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
@@ -2720,7 +2752,7 @@ private:
|
||||
auto const executions = meta[sfHookExecutions.jsonName];
|
||||
auto const execution = executions[0u][sfHookExecution.jsonName];
|
||||
BEAST_EXPECT(execution[sfHookResult.jsonName] == 3);
|
||||
BEAST_EXPECT(execution[sfHookReturnString.jsonName] == "00000000");
|
||||
BEAST_EXPECT(execution[sfHookReturnString.jsonName] == "00000001");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3020,7 +3052,7 @@ private:
|
||||
|
||||
// otxn: account
|
||||
// tsh dest
|
||||
// w/s: weak
|
||||
// w/s: strong
|
||||
{
|
||||
test::jtx::Env env{
|
||||
*this,
|
||||
@@ -3295,19 +3327,18 @@ private:
|
||||
// | otxn | tfBurnable | tsh | mint | burn | buy | sell | cancel
|
||||
// | O | false | O | N | S | S | S | S
|
||||
// | O | false | I | N | W | W | W | N
|
||||
// | O | false | B | N | N | N | S | N
|
||||
// | O | true | B | N | N | N | S | N
|
||||
// | O | false | B | N | N | N | S | W
|
||||
// | O | true | B | N | N | N | S | W
|
||||
// | O | true | O | N | S | S | S | S
|
||||
// | O | true | I | N | W | S | S | N
|
||||
// | I | false | O | N | N | N | N | N
|
||||
// | I | false | I | S | N | N | N | N
|
||||
// | I | false | B | N | N | N | N | N
|
||||
// | I | false | B | S | N | N | N | N
|
||||
// | I | true | O | N | W | N | N | N
|
||||
// | I | true | I | S | S | N | N | N
|
||||
// | I | true | B | N | N | N | N | N
|
||||
// | I | true | B | S | N | N | N | N
|
||||
// | B | true | O | N | N | ? | N | N
|
||||
// | B | true | B | N | N | ? | N | N
|
||||
|
||||
void
|
||||
testURITokenBurnTSH(FeatureBitset features)
|
||||
{
|
||||
@@ -3373,7 +3404,7 @@ private:
|
||||
// otxn: owner
|
||||
// flag: not burnable
|
||||
// tsh issuer
|
||||
// w/s: strong
|
||||
// w/s: weak
|
||||
{
|
||||
test::jtx::Env env{
|
||||
*this,
|
||||
@@ -3389,6 +3420,9 @@ private:
|
||||
auto const tid = uritoken::tokenid(issuer, uri);
|
||||
std::string const hexid{strHex(tid)};
|
||||
|
||||
env(fset(issuer, asfTshCollect));
|
||||
env.close();
|
||||
|
||||
// mint uritoken
|
||||
env(uritoken::mint(issuer, uri),
|
||||
uritoken::dest(owner),
|
||||
@@ -3403,7 +3437,7 @@ private:
|
||||
env.close();
|
||||
|
||||
// set tsh hook
|
||||
env(hook(issuer, {{hso(TshHook, overrideFlag)}}, 0),
|
||||
env(hook(issuer, {{hso(TshHook, collectFlag)}}, 0),
|
||||
fee(XRP(1)),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
@@ -3421,7 +3455,7 @@ private:
|
||||
auto const executions = meta[sfHookExecutions.jsonName];
|
||||
auto const execution = executions[0u][sfHookExecution.jsonName];
|
||||
BEAST_EXPECT(execution[sfHookResult.jsonName] == 3);
|
||||
BEAST_EXPECT(execution[sfHookReturnString.jsonName] == "00000000");
|
||||
BEAST_EXPECT(execution[sfHookReturnString.jsonName] == "00000001");
|
||||
}
|
||||
|
||||
// otxn: owner
|
||||
@@ -3482,7 +3516,7 @@ private:
|
||||
// otxn: owner
|
||||
// flag: burnable
|
||||
// tsh issuer
|
||||
// w/s: strong
|
||||
// w/s: weak
|
||||
{
|
||||
test::jtx::Env env{
|
||||
*this,
|
||||
@@ -3498,6 +3532,9 @@ private:
|
||||
auto const tid = uritoken::tokenid(issuer, uri);
|
||||
std::string const hexid{strHex(tid)};
|
||||
|
||||
env(fset(issuer, asfTshCollect));
|
||||
env.close();
|
||||
|
||||
// mint uritoken
|
||||
env(uritoken::mint(issuer, uri),
|
||||
uritoken::dest(owner),
|
||||
@@ -3513,7 +3550,7 @@ private:
|
||||
env.close();
|
||||
|
||||
// set tsh hook
|
||||
env(hook(issuer, {{hso(TshHook, overrideFlag)}}, 0),
|
||||
env(hook(issuer, {{hso(TshHook, collectFlag)}}, 0),
|
||||
fee(XRP(1)),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
@@ -3531,13 +3568,13 @@ private:
|
||||
auto const executions = meta[sfHookExecutions.jsonName];
|
||||
auto const execution = executions[0u][sfHookExecution.jsonName];
|
||||
BEAST_EXPECT(execution[sfHookResult.jsonName] == 3);
|
||||
BEAST_EXPECT(execution[sfHookReturnString.jsonName] == "00000000");
|
||||
BEAST_EXPECT(execution[sfHookReturnString.jsonName] == "00000001");
|
||||
}
|
||||
|
||||
// otxn: issuer
|
||||
// flag: burnable
|
||||
// tsh owner
|
||||
// w/s: strong
|
||||
// w/s: weak
|
||||
{
|
||||
test::jtx::Env env{
|
||||
*this,
|
||||
@@ -3553,6 +3590,9 @@ private:
|
||||
auto const tid = uritoken::tokenid(issuer, uri);
|
||||
std::string const hexid{strHex(tid)};
|
||||
|
||||
env(fset(owner, asfTshCollect));
|
||||
env.close();
|
||||
|
||||
// mint uritoken
|
||||
env(uritoken::mint(issuer, uri),
|
||||
uritoken::dest(owner),
|
||||
@@ -3568,7 +3608,7 @@ private:
|
||||
env.close();
|
||||
|
||||
// set tsh hook
|
||||
env(hook(owner, {{hso(TshHook, overrideFlag)}}, 0),
|
||||
env(hook(owner, {{hso(TshHook, collectFlag)}}, 0),
|
||||
fee(XRP(1)),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
@@ -3586,7 +3626,7 @@ private:
|
||||
auto const executions = meta[sfHookExecutions.jsonName];
|
||||
auto const execution = executions[0u][sfHookExecution.jsonName];
|
||||
BEAST_EXPECT(execution[sfHookResult.jsonName] == 3);
|
||||
BEAST_EXPECT(execution[sfHookReturnString.jsonName] == "00000000");
|
||||
BEAST_EXPECT(execution[sfHookReturnString.jsonName] == "00000001");
|
||||
}
|
||||
|
||||
// otxn: issuer
|
||||
@@ -3653,213 +3693,8 @@ private:
|
||||
using namespace test::jtx;
|
||||
using namespace std::literals;
|
||||
|
||||
// otxn: owner
|
||||
// flag: not burnable
|
||||
// tsh owner
|
||||
// w/s: strong
|
||||
{
|
||||
test::jtx::Env env{
|
||||
*this,
|
||||
network::makeNetworkConfig(21337, "10", "1000000", "200000"),
|
||||
features};
|
||||
|
||||
auto const issuer = Account("alice");
|
||||
auto const owner = Account("bob");
|
||||
env.fund(XRP(1000), issuer, owner);
|
||||
env.close();
|
||||
|
||||
std::string const uri(2, '?');
|
||||
auto const tid = uritoken::tokenid(issuer, uri);
|
||||
std::string const hexid{strHex(tid)};
|
||||
|
||||
// mint uritoken
|
||||
env(uritoken::mint(issuer, uri),
|
||||
uritoken::dest(owner),
|
||||
uritoken::amt(XRP(1)),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
|
||||
// set tsh hook
|
||||
env(hook(owner, {{hso(TshHook, overrideFlag)}}, 0),
|
||||
fee(XRP(1)),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
|
||||
// buy uritoken
|
||||
env(uritoken::buy(owner, hexid),
|
||||
uritoken::amt(XRP(1)),
|
||||
fee(XRP(1)),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
|
||||
// verify tsh hook triggered
|
||||
Json::Value params;
|
||||
params[jss::transaction] =
|
||||
env.tx()->getJson(JsonOptions::none)[jss::hash];
|
||||
auto const jrr = env.rpc("json", "tx", to_string(params));
|
||||
auto const meta = jrr[jss::result][jss::meta];
|
||||
auto const executions = meta[sfHookExecutions.jsonName];
|
||||
auto const execution = executions[0u][sfHookExecution.jsonName];
|
||||
BEAST_EXPECT(execution[sfHookResult.jsonName] == 3);
|
||||
BEAST_EXPECT(execution[sfHookReturnString.jsonName] == "00000000");
|
||||
}
|
||||
|
||||
// otxn: owner
|
||||
// flag: not burnable
|
||||
// tsh issuer
|
||||
// w/s: strong
|
||||
{
|
||||
test::jtx::Env env{
|
||||
*this,
|
||||
network::makeNetworkConfig(21337, "10", "1000000", "200000"),
|
||||
features};
|
||||
|
||||
auto const issuer = Account("alice");
|
||||
auto const owner = Account("bob");
|
||||
env.fund(XRP(1000), issuer, owner);
|
||||
env.close();
|
||||
|
||||
std::string const uri(2, '?');
|
||||
auto const tid = uritoken::tokenid(issuer, uri);
|
||||
std::string const hexid{strHex(tid)};
|
||||
|
||||
// mint uritoken
|
||||
env(uritoken::mint(issuer, uri),
|
||||
uritoken::dest(owner),
|
||||
uritoken::amt(XRP(1)),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
|
||||
// set tsh hook
|
||||
env(hook(issuer, {{hso(TshHook, overrideFlag)}}, 0),
|
||||
fee(XRP(1)),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
|
||||
// buy uritoken
|
||||
env(uritoken::buy(owner, hexid),
|
||||
uritoken::amt(XRP(1)),
|
||||
fee(XRP(1)),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
|
||||
// verify tsh hook triggered
|
||||
Json::Value params;
|
||||
params[jss::transaction] =
|
||||
env.tx()->getJson(JsonOptions::none)[jss::hash];
|
||||
auto const jrr = env.rpc("json", "tx", to_string(params));
|
||||
auto const meta = jrr[jss::result][jss::meta];
|
||||
auto const executions = meta[sfHookExecutions.jsonName];
|
||||
auto const execution = executions[0u][sfHookExecution.jsonName];
|
||||
BEAST_EXPECT(execution[sfHookResult.jsonName] == 3);
|
||||
BEAST_EXPECT(execution[sfHookReturnString.jsonName] == "00000000");
|
||||
}
|
||||
|
||||
// otxn: owner
|
||||
// flag: burnable
|
||||
// tsh owner
|
||||
// w/s: strong
|
||||
{
|
||||
test::jtx::Env env{
|
||||
*this,
|
||||
network::makeNetworkConfig(21337, "10", "1000000", "200000"),
|
||||
features};
|
||||
|
||||
auto const issuer = Account("alice");
|
||||
auto const owner = Account("bob");
|
||||
env.fund(XRP(1000), issuer, owner);
|
||||
env.close();
|
||||
|
||||
std::string const uri(2, '?');
|
||||
auto const tid = uritoken::tokenid(issuer, uri);
|
||||
std::string const hexid{strHex(tid)};
|
||||
|
||||
// mint uritoken
|
||||
env(uritoken::mint(issuer, uri),
|
||||
uritoken::dest(owner),
|
||||
uritoken::amt(XRP(1)),
|
||||
txflags(tfBurnable),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
|
||||
// set tsh hook
|
||||
env(hook(owner, {{hso(TshHook, overrideFlag)}}, 0),
|
||||
fee(XRP(1)),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
|
||||
// buy uritoken
|
||||
env(uritoken::buy(owner, hexid),
|
||||
uritoken::amt(XRP(1)),
|
||||
fee(XRP(1)),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
|
||||
// verify tsh hook triggered
|
||||
Json::Value params;
|
||||
params[jss::transaction] =
|
||||
env.tx()->getJson(JsonOptions::none)[jss::hash];
|
||||
auto const jrr = env.rpc("json", "tx", to_string(params));
|
||||
auto const meta = jrr[jss::result][jss::meta];
|
||||
auto const executions = meta[sfHookExecutions.jsonName];
|
||||
auto const execution = executions[0u][sfHookExecution.jsonName];
|
||||
BEAST_EXPECT(execution[sfHookResult.jsonName] == 3);
|
||||
BEAST_EXPECT(execution[sfHookReturnString.jsonName] == "00000000");
|
||||
}
|
||||
|
||||
// otxn: owner
|
||||
// flag: burnable
|
||||
// tsh issuer
|
||||
// w/s: strong
|
||||
{
|
||||
test::jtx::Env env{
|
||||
*this,
|
||||
network::makeNetworkConfig(21337, "10", "1000000", "200000"),
|
||||
features};
|
||||
|
||||
auto const issuer = Account("alice");
|
||||
auto const owner = Account("bob");
|
||||
env.fund(XRP(1000), issuer, owner);
|
||||
env.close();
|
||||
|
||||
std::string const uri(2, '?');
|
||||
auto const tid = uritoken::tokenid(issuer, uri);
|
||||
std::string const hexid{strHex(tid)};
|
||||
|
||||
// mint uritoken
|
||||
env(uritoken::mint(issuer, uri),
|
||||
uritoken::dest(owner),
|
||||
uritoken::amt(XRP(1)),
|
||||
txflags(tfBurnable),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
|
||||
// set tsh hook
|
||||
env(hook(issuer, {{hso(TshHook, overrideFlag)}}, 0),
|
||||
fee(XRP(1)),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
|
||||
// buy uritoken
|
||||
env(uritoken::buy(owner, hexid),
|
||||
uritoken::amt(XRP(1)),
|
||||
fee(XRP(1)),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
|
||||
// verify tsh hook triggered
|
||||
Json::Value params;
|
||||
params[jss::transaction] =
|
||||
env.tx()->getJson(JsonOptions::none)[jss::hash];
|
||||
auto const jrr = env.rpc("json", "tx", to_string(params));
|
||||
auto const meta = jrr[jss::result][jss::meta];
|
||||
auto const executions = meta[sfHookExecutions.jsonName];
|
||||
auto const execution = executions[0u][sfHookExecution.jsonName];
|
||||
BEAST_EXPECT(execution[sfHookResult.jsonName] == 3);
|
||||
BEAST_EXPECT(execution[sfHookReturnString.jsonName] == "00000000");
|
||||
}
|
||||
|
||||
// otxn: buyer
|
||||
// flag: not burnable
|
||||
// tsh owner
|
||||
// w/s: strong
|
||||
{
|
||||
@@ -3925,8 +3760,9 @@ private:
|
||||
}
|
||||
|
||||
// otxn: buyer
|
||||
// tsh buyer
|
||||
// w/s: strong
|
||||
// flag: not burnable
|
||||
// tsh issuer
|
||||
// w/s: weak
|
||||
{
|
||||
test::jtx::Env env{
|
||||
*this,
|
||||
@@ -3943,6 +3779,9 @@ private:
|
||||
auto const tid = uritoken::tokenid(issuer, uri);
|
||||
std::string const hexid{strHex(tid)};
|
||||
|
||||
env(fset(issuer, asfTshCollect));
|
||||
env.close();
|
||||
|
||||
// mint uritoken
|
||||
env(uritoken::mint(issuer, uri),
|
||||
uritoken::dest(owner),
|
||||
@@ -3965,7 +3804,141 @@ private:
|
||||
env.close();
|
||||
|
||||
// set tsh hook
|
||||
env(hook(buyer, {{hso(TshHook, overrideFlag)}}, 0),
|
||||
env(hook(issuer, {{hso(TshHook, collectFlag)}}, 0),
|
||||
fee(XRP(1)),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
|
||||
// buy uritoken
|
||||
env(uritoken::buy(buyer, hexid),
|
||||
uritoken::amt(XRP(1)),
|
||||
fee(XRP(1)),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
|
||||
// verify tsh hook triggered
|
||||
Json::Value params;
|
||||
params[jss::transaction] =
|
||||
env.tx()->getJson(JsonOptions::none)[jss::hash];
|
||||
auto const jrr = env.rpc("json", "tx", to_string(params));
|
||||
auto const meta = jrr[jss::result][jss::meta];
|
||||
auto const executions = meta[sfHookExecutions.jsonName];
|
||||
auto const execution = executions[0u][sfHookExecution.jsonName];
|
||||
BEAST_EXPECT(execution[sfHookResult.jsonName] == 3);
|
||||
BEAST_EXPECT(execution[sfHookReturnString.jsonName] == "00000001");
|
||||
}
|
||||
|
||||
// otxn: buyer
|
||||
// flag: burnable
|
||||
// tsh owner
|
||||
// w/s: strong
|
||||
{
|
||||
test::jtx::Env env{
|
||||
*this,
|
||||
network::makeNetworkConfig(21337, "10", "1000000", "200000"),
|
||||
features};
|
||||
|
||||
auto const issuer = Account("alice");
|
||||
auto const owner = Account("bob");
|
||||
auto const buyer = Account("carol");
|
||||
env.fund(XRP(1000), issuer, owner, buyer);
|
||||
env.close();
|
||||
|
||||
std::string const uri(2, '?');
|
||||
auto const tid = uritoken::tokenid(issuer, uri);
|
||||
std::string const hexid{strHex(tid)};
|
||||
|
||||
// mint uritoken
|
||||
env(uritoken::mint(issuer, uri),
|
||||
uritoken::dest(owner),
|
||||
uritoken::amt(XRP(1)),
|
||||
txflags(tfBurnable),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
|
||||
// buy uritoken
|
||||
env(uritoken::buy(owner, hexid),
|
||||
uritoken::amt(XRP(1)),
|
||||
fee(XRP(1)),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
|
||||
// sell uritoken
|
||||
env(uritoken::sell(owner, hexid),
|
||||
uritoken::dest(buyer),
|
||||
uritoken::amt(XRP(1)),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
|
||||
// set tsh hook
|
||||
env(hook(owner, {{hso(TshHook, overrideFlag)}}, 0),
|
||||
fee(XRP(1)),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
|
||||
// buy uritoken
|
||||
env(uritoken::buy(buyer, hexid),
|
||||
uritoken::amt(XRP(1)),
|
||||
fee(XRP(1)),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
|
||||
// verify tsh hook triggered
|
||||
Json::Value params;
|
||||
params[jss::transaction] =
|
||||
env.tx()->getJson(JsonOptions::none)[jss::hash];
|
||||
auto const jrr = env.rpc("json", "tx", to_string(params));
|
||||
auto const meta = jrr[jss::result][jss::meta];
|
||||
auto const executions = meta[sfHookExecutions.jsonName];
|
||||
auto const execution = executions[0u][sfHookExecution.jsonName];
|
||||
BEAST_EXPECT(execution[sfHookResult.jsonName] == 3);
|
||||
BEAST_EXPECT(execution[sfHookReturnString.jsonName] == "00000000");
|
||||
}
|
||||
|
||||
// otxn: buyer
|
||||
// flag: burnable
|
||||
// tsh issuer
|
||||
// w/s: strong
|
||||
{
|
||||
test::jtx::Env env{
|
||||
*this,
|
||||
network::makeNetworkConfig(21337, "10", "1000000", "200000"),
|
||||
features};
|
||||
|
||||
auto const issuer = Account("alice");
|
||||
auto const owner = Account("bob");
|
||||
auto const buyer = Account("carol");
|
||||
env.fund(XRP(1000), issuer, owner, buyer);
|
||||
env.close();
|
||||
|
||||
std::string const uri(2, '?');
|
||||
auto const tid = uritoken::tokenid(issuer, uri);
|
||||
std::string const hexid{strHex(tid)};
|
||||
|
||||
// mint uritoken
|
||||
env(uritoken::mint(issuer, uri),
|
||||
uritoken::dest(owner),
|
||||
uritoken::amt(XRP(1)),
|
||||
txflags(tfBurnable),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
|
||||
// buy uritoken
|
||||
env(uritoken::buy(owner, hexid),
|
||||
uritoken::amt(XRP(1)),
|
||||
fee(XRP(1)),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
|
||||
// sell uritoken
|
||||
env(uritoken::sell(owner, hexid),
|
||||
uritoken::dest(buyer),
|
||||
uritoken::amt(XRP(1)),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
|
||||
// set tsh hook
|
||||
env(hook(issuer, {{hso(TshHook, overrideFlag)}}, 0),
|
||||
fee(XRP(1)),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
@@ -4063,7 +4036,7 @@ private:
|
||||
// otxn: owner
|
||||
// flag: not burnable
|
||||
// tsh buyer
|
||||
// w/s: none
|
||||
// w/s: weak
|
||||
{
|
||||
test::jtx::Env env{
|
||||
*this,
|
||||
@@ -4120,13 +4093,15 @@ private:
|
||||
auto const jrr = env.rpc("json", "tx", to_string(params));
|
||||
auto const meta = jrr[jss::result][jss::meta];
|
||||
auto const executions = meta[sfHookExecutions.jsonName];
|
||||
BEAST_EXPECT(executions.size() == 0);
|
||||
auto const execution = executions[0u][sfHookExecution.jsonName];
|
||||
BEAST_EXPECT(execution[sfHookResult.jsonName] == 3);
|
||||
BEAST_EXPECT(execution[sfHookReturnString.jsonName] == "00000001");
|
||||
}
|
||||
|
||||
// otxn: owner
|
||||
// flag: burnable
|
||||
// tsh buyer
|
||||
// w/s: none
|
||||
// w/s: weak
|
||||
{
|
||||
test::jtx::Env env{
|
||||
*this,
|
||||
@@ -4184,7 +4159,9 @@ private:
|
||||
auto const jrr = env.rpc("json", "tx", to_string(params));
|
||||
auto const meta = jrr[jss::result][jss::meta];
|
||||
auto const executions = meta[sfHookExecutions.jsonName];
|
||||
BEAST_EXPECT(executions.size() == 0);
|
||||
auto const execution = executions[0u][sfHookExecution.jsonName];
|
||||
BEAST_EXPECT(execution[sfHookResult.jsonName] == 3);
|
||||
BEAST_EXPECT(execution[sfHookReturnString.jsonName] == "00000001");
|
||||
}
|
||||
|
||||
// otxn: owner
|
||||
@@ -4675,7 +4652,7 @@ private:
|
||||
// otxn: issuer
|
||||
// flag: not burnable
|
||||
// tsh buyer
|
||||
// w/s: none
|
||||
// w/s: strong
|
||||
{
|
||||
test::jtx::Env env{
|
||||
*this,
|
||||
@@ -4687,15 +4664,12 @@ private:
|
||||
env.fund(XRP(1000), issuer, buyer);
|
||||
env.close();
|
||||
|
||||
env(fset(buyer, asfTshCollect));
|
||||
env.close();
|
||||
|
||||
std::string const uri(2, '?');
|
||||
auto const tid = uritoken::tokenid(issuer, uri);
|
||||
std::string const hexid{strHex(tid)};
|
||||
|
||||
// set tsh hook
|
||||
env(hook(buyer, {{hso(TshHook, collectFlag)}}, 0),
|
||||
env(hook(buyer, {{hso(TshHook, overrideFlag)}}, 0),
|
||||
fee(XRP(1)),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
@@ -4715,7 +4689,9 @@ private:
|
||||
auto const jrr = env.rpc("json", "tx", to_string(params));
|
||||
auto const meta = jrr[jss::result][jss::meta];
|
||||
auto const executions = meta[sfHookExecutions.jsonName];
|
||||
BEAST_EXPECT(executions.size() == 0);
|
||||
auto const execution = executions[0u][sfHookExecution.jsonName];
|
||||
BEAST_EXPECT(execution[sfHookResult.jsonName] == 3);
|
||||
BEAST_EXPECT(execution[sfHookReturnString.jsonName] == "00000000");
|
||||
}
|
||||
|
||||
// otxn: issuer
|
||||
@@ -4767,7 +4743,7 @@ private:
|
||||
// otxn: issuer
|
||||
// flag: burnable
|
||||
// tsh buyer
|
||||
// w/s: none
|
||||
// w/s: strong
|
||||
{
|
||||
test::jtx::Env env{
|
||||
*this,
|
||||
@@ -4779,15 +4755,12 @@ private:
|
||||
env.fund(XRP(1000), issuer, buyer);
|
||||
env.close();
|
||||
|
||||
env(fset(buyer, asfTshCollect));
|
||||
env.close();
|
||||
|
||||
std::string const uri(2, '?');
|
||||
auto const tid = uritoken::tokenid(issuer, uri);
|
||||
std::string const hexid{strHex(tid)};
|
||||
|
||||
// set tsh hook
|
||||
env(hook(buyer, {{hso(TshHook, collectFlag)}}, 0),
|
||||
env(hook(buyer, {{hso(TshHook, overrideFlag)}}, 0),
|
||||
fee(XRP(1)),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
@@ -4808,7 +4781,9 @@ private:
|
||||
auto const jrr = env.rpc("json", "tx", to_string(params));
|
||||
auto const meta = jrr[jss::result][jss::meta];
|
||||
auto const executions = meta[sfHookExecutions.jsonName];
|
||||
BEAST_EXPECT(executions.size() == 0);
|
||||
auto const execution = executions[0u][sfHookExecution.jsonName];
|
||||
BEAST_EXPECT(execution[sfHookResult.jsonName] == 3);
|
||||
BEAST_EXPECT(execution[sfHookReturnString.jsonName] == "00000000");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user