mirror of
https://github.com/Xahau/xahaud.git
synced 2026-10-24 04:37:10 +00:00
Compare commits
16
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b926e2e2f6 | ||
|
|
2876ee146d | ||
|
|
94fe1f7b29 | ||
|
|
2d93c50bcc | ||
|
|
a9f7bc81c3 | ||
|
|
10ae534300 | ||
|
|
97ab309a09 | ||
|
|
6cb07b0000 | ||
|
|
049efbcdc0 | ||
|
|
9f449e97bc | ||
|
|
6561cd7f58 | ||
|
|
3b353e146f | ||
|
|
7295577cdd | ||
|
|
27b91f997c | ||
|
|
75b760debe | ||
|
|
3f7e15893e |
No files matched your search
@@ -45,5 +45,7 @@
|
||||
#define INVALID_KEY -41
|
||||
#define NOT_A_STRING -42
|
||||
#define MEM_OVERLAP -43
|
||||
#define TOO_MANY_STATE_MODIFICATIONS -44
|
||||
#define TOO_MANY_NAMESPACES -45
|
||||
#define HOOK_ERROR_CODES
|
||||
#endif //HOOK_ERROR_CODES
|
||||
@@ -54,6 +54,12 @@ maxHookChainLength(void)
|
||||
return 10;
|
||||
}
|
||||
|
||||
inline uint32_t
|
||||
maxNamespaces(void)
|
||||
{
|
||||
return 256;
|
||||
}
|
||||
|
||||
enum TSHFlags : uint8_t {
|
||||
tshNONE = 0b000,
|
||||
tshROLLBACK = 0b001,
|
||||
@@ -313,6 +319,7 @@ enum hook_return_code : int64_t {
|
||||
MEM_OVERLAP = -43, // one or more specified buffers are the same memory
|
||||
TOO_MANY_STATE_MODIFICATIONS = -44, // more than 5000 modified state
|
||||
// entires in the combined hook chains
|
||||
TOO_MANY_NAMESPACES = -45
|
||||
};
|
||||
|
||||
enum ExitType : uint8_t {
|
||||
|
||||
@@ -29,8 +29,9 @@ isEmittedTxn(ripple::STTx const& tx);
|
||||
// only upon tesSuccess for the otxn.
|
||||
class HookStateMap : public std::map<
|
||||
ripple::AccountID, // account that owns the state
|
||||
std::pair<
|
||||
std::tuple<
|
||||
int64_t, // remaining available ownercount
|
||||
int64_t, // total namespace count
|
||||
std::map<
|
||||
ripple::uint256, // namespace
|
||||
std::map<
|
||||
@@ -44,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1287,7 +1305,7 @@ lookup_state_cache(
|
||||
if (stateMap.find(acc) == stateMap.end())
|
||||
return std::nullopt;
|
||||
|
||||
auto& stateMapAcc = stateMap[acc].second;
|
||||
auto& stateMapAcc = std::get<2>(stateMap[acc]);
|
||||
if (stateMapAcc.find(ns) == stateMapAcc.end())
|
||||
return std::nullopt;
|
||||
|
||||
@@ -1312,18 +1330,22 @@ set_state_cache(
|
||||
bool modified)
|
||||
{
|
||||
auto& stateMap = hookCtx.result.stateMap;
|
||||
auto& view = hookCtx.applyCtx.view();
|
||||
|
||||
if (modified && stateMap.modified_entry_count >= max_state_modifications)
|
||||
return TOO_MANY_STATE_MODIFICATIONS;
|
||||
|
||||
bool const createNamespace = view.rules().enabled(fixXahauV1) &&
|
||||
!view.exists(keylet::hookStateDir(acc, ns));
|
||||
|
||||
if (stateMap.find(acc) == stateMap.end())
|
||||
{
|
||||
// if this is the first time this account has been interacted with
|
||||
// we will compute how many available reserve positions there are
|
||||
auto const& fees = hookCtx.applyCtx.view().fees();
|
||||
|
||||
auto const accSLE =
|
||||
hookCtx.applyCtx.view().read(ripple::keylet::account(acc));
|
||||
auto const accSLE = view.read(ripple::keylet::account(acc));
|
||||
|
||||
if (!accSLE)
|
||||
return DOESNT_EXIST;
|
||||
|
||||
@@ -1342,15 +1364,32 @@ set_state_cache(
|
||||
if (availableForReserves < 1 && modified)
|
||||
return RESERVE_INSUFFICIENT;
|
||||
|
||||
int64_t namespaceCount = accSLE->isFieldPresent(sfHookNamespaces)
|
||||
? accSLE->getFieldV256(sfHookNamespaces).size()
|
||||
: 0;
|
||||
|
||||
if (createNamespace)
|
||||
{
|
||||
// overflow should never ever happen but check anyway
|
||||
if (namespaceCount + 1 < namespaceCount)
|
||||
return INTERNAL_ERROR;
|
||||
|
||||
if (++namespaceCount > hook::maxNamespaces())
|
||||
return TOO_MANY_NAMESPACES;
|
||||
}
|
||||
|
||||
stateMap.modified_entry_count++;
|
||||
|
||||
stateMap[acc] = {
|
||||
availableForReserves - 1, {{ns, {{key, {modified, data}}}}}};
|
||||
availableForReserves - 1,
|
||||
namespaceCount,
|
||||
{{ns, {{key, {modified, data}}}}}};
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto& stateMapAcc = stateMap[acc].second;
|
||||
auto& availableForReserves = stateMap[acc].first;
|
||||
auto& availableForReserves = std::get<0>(stateMap[acc]);
|
||||
auto& namespaceCount = std::get<1>(stateMap[acc]);
|
||||
auto& stateMapAcc = std::get<2>(stateMap[acc]);
|
||||
bool const canReserveNew = availableForReserves > 0;
|
||||
|
||||
if (stateMapAcc.find(ns) == stateMapAcc.end())
|
||||
@@ -1360,6 +1399,18 @@ set_state_cache(
|
||||
if (!canReserveNew)
|
||||
return RESERVE_INSUFFICIENT;
|
||||
|
||||
if (createNamespace)
|
||||
{
|
||||
// overflow should never ever happen but check anyway
|
||||
if (namespaceCount + 1 < namespaceCount)
|
||||
return INTERNAL_ERROR;
|
||||
|
||||
if (namespaceCount + 1 > hook::maxNamespaces())
|
||||
return TOO_MANY_NAMESPACES;
|
||||
|
||||
namespaceCount++;
|
||||
}
|
||||
|
||||
availableForReserves--;
|
||||
stateMap.modified_entry_count++;
|
||||
}
|
||||
@@ -1488,6 +1539,13 @@ DEFINE_HOOK_FUNCTION(
|
||||
auto const key = make_state_key(
|
||||
std::string_view{(const char*)(memory + kread_ptr), (size_t)kread_len});
|
||||
|
||||
if (view.rules().enabled(fixXahauV1))
|
||||
{
|
||||
auto const sleAccount = view.peek(hookCtx.result.accountKeylet);
|
||||
if (!sleAccount)
|
||||
return tefINTERNAL;
|
||||
}
|
||||
|
||||
if (!key)
|
||||
return INTERNAL_ERROR;
|
||||
|
||||
@@ -1610,7 +1668,7 @@ hook::finalizeHookState(
|
||||
for (const auto& accEntry : stateMap)
|
||||
{
|
||||
const auto& acc = accEntry.first;
|
||||
for (const auto& nsEntry : accEntry.second.second)
|
||||
for (const auto& nsEntry : std::get<2>(accEntry.second))
|
||||
{
|
||||
const auto& ns = nsEntry.first;
|
||||
for (const auto& cacheEntry : nsEntry.second)
|
||||
|
||||
@@ -39,10 +39,26 @@ CancelOffer::preflight(PreflightContext const& ctx)
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
|
||||
if (!ctx.tx[sfOfferSequence])
|
||||
if (ctx.rules.enabled(fixXahauV1))
|
||||
{
|
||||
JLOG(ctx.j.trace()) << "CancelOffer::preflight: missing sequence";
|
||||
return temBAD_SEQUENCE;
|
||||
if ((!ctx.tx.isFieldPresent(sfOfferSequence) &&
|
||||
!ctx.tx.isFieldPresent(sfOfferID)) ||
|
||||
(ctx.tx.isFieldPresent(sfOfferSequence) &&
|
||||
ctx.tx.isFieldPresent(sfOfferID)))
|
||||
{
|
||||
JLOG(ctx.j.trace())
|
||||
<< "CancelOffer::preflight: invalid sequence or offer id";
|
||||
return temBAD_SEQUENCE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ctx.tx.isFieldPresent(sfOfferSequence) ||
|
||||
ctx.tx[sfOfferSequence] == 0)
|
||||
{
|
||||
JLOG(ctx.j.trace()) << "CancelOffer::preflight: missing sequence";
|
||||
return temBAD_SEQUENCE;
|
||||
}
|
||||
}
|
||||
|
||||
return preflight2(ctx);
|
||||
@@ -54,29 +70,18 @@ TER
|
||||
CancelOffer::preclaim(PreclaimContext const& ctx)
|
||||
{
|
||||
auto const id = ctx.tx[sfAccount];
|
||||
auto const offerSequence = ctx.tx[sfOfferSequence];
|
||||
|
||||
auto const sle = ctx.view.read(keylet::account(id));
|
||||
if (!sle)
|
||||
return terNO_ACCOUNT;
|
||||
|
||||
bool hooksEnabled = ctx.view.rules().enabled(featureHooks);
|
||||
auto const offerSequence = ctx.tx[~sfOfferSequence];
|
||||
|
||||
auto const offerID = ctx.tx[~sfOfferID];
|
||||
|
||||
if ((*sle)[sfSequence] <= offerSequence)
|
||||
if (offerSequence && (*sle)[sfSequence] <= *offerSequence)
|
||||
{
|
||||
if (hooksEnabled && offerID && offerSequence == 0)
|
||||
{
|
||||
// pass, here the txn provides offerID instead of offerSequence
|
||||
}
|
||||
else
|
||||
{
|
||||
JLOG(ctx.j.trace())
|
||||
<< "Malformed transaction: "
|
||||
<< "Sequence " << offerSequence << " is invalid.";
|
||||
return temBAD_SEQUENCE;
|
||||
}
|
||||
JLOG(ctx.j.trace()) << "Malformed transaction: "
|
||||
<< "Sequence " << *offerSequence << " is invalid.";
|
||||
return temBAD_SEQUENCE;
|
||||
}
|
||||
|
||||
return tesSUCCESS;
|
||||
@@ -87,36 +92,32 @@ CancelOffer::preclaim(PreclaimContext const& ctx)
|
||||
TER
|
||||
CancelOffer::doApply()
|
||||
{
|
||||
auto const offerSequence = ctx_.tx[sfOfferSequence];
|
||||
|
||||
auto const sle = view().read(keylet::account(account_));
|
||||
if (!sle)
|
||||
return tefINTERNAL;
|
||||
|
||||
auto const offerSequence = ctx_.tx[~sfOfferSequence];
|
||||
auto const offerID = ctx_.tx[~sfOfferID];
|
||||
|
||||
bool hooksEnabled = view().rules().enabled(featureHooks);
|
||||
|
||||
std::optional<uint256> offerID;
|
||||
|
||||
if (hooksEnabled)
|
||||
offerID = ctx_.tx[~sfOfferID];
|
||||
|
||||
Keylet cancel = hooksEnabled && offerID && offerSequence == 0
|
||||
Keylet cancel = hooksEnabled && offerID && !offerSequence
|
||||
? Keylet(ltOFFER, *offerID)
|
||||
: keylet::offer(account_, offerSequence);
|
||||
: keylet::offer(account_, *offerSequence);
|
||||
|
||||
if (auto sleOffer = view().peek(cancel))
|
||||
{
|
||||
if (offerID)
|
||||
JLOG(j_.debug()) << "Trying to cancel offer :" << *offerID;
|
||||
else
|
||||
JLOG(j_.debug()) << "Trying to cancel offer #" << offerSequence;
|
||||
JLOG(j_.debug()) << "Trying to cancel offer #" << *offerSequence;
|
||||
return offerDelete(view(), sleOffer, ctx_.app.journal("View"));
|
||||
}
|
||||
|
||||
if (offerID)
|
||||
JLOG(j_.debug()) << "Offer :" << *offerID << " can't be found.";
|
||||
else
|
||||
JLOG(j_.debug()) << "Offer #" << offerSequence << " can't be found.";
|
||||
JLOG(j_.debug()) << "Offer #" << *offerSequence << " can't be found.";
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -431,6 +431,10 @@ EscrowFinish::preflight(PreflightContext const& ctx)
|
||||
}
|
||||
}
|
||||
|
||||
if (!ctx.tx.isFieldPresent(sfEscrowID) &&
|
||||
!ctx.tx.isFieldPresent(sfOfferSequence))
|
||||
return temMALFORMED;
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
@@ -456,13 +460,21 @@ EscrowFinish::doApply()
|
||||
return temDISABLED;
|
||||
|
||||
std::optional<uint256> escrowID = ctx_.tx[~sfEscrowID];
|
||||
std::optional<std::uint32_t> offerSequence = ctx_.tx[~sfOfferSequence];
|
||||
|
||||
if (escrowID && ctx_.tx[sfOfferSequence] != 0)
|
||||
return temMALFORMED;
|
||||
if (!view().rules().enabled(fixXahauV1))
|
||||
{
|
||||
if (escrowID && ctx_.tx[sfOfferSequence] != 0)
|
||||
return temMALFORMED;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (escrowID && offerSequence)
|
||||
return temMALFORMED;
|
||||
}
|
||||
|
||||
Keylet k = escrowID
|
||||
? Keylet(ltESCROW, *escrowID)
|
||||
: keylet::escrow(ctx_.tx[sfOwner], ctx_.tx[sfOfferSequence]);
|
||||
Keylet k = escrowID ? Keylet(ltESCROW, *escrowID)
|
||||
: keylet::escrow(ctx_.tx[sfOwner], *offerSequence);
|
||||
|
||||
auto const slep = ctx_.view().peek(k);
|
||||
if (!slep)
|
||||
@@ -692,6 +704,10 @@ EscrowCancel::preflight(PreflightContext const& ctx)
|
||||
if (auto const ret = preflight1(ctx); !isTesSuccess(ret))
|
||||
return ret;
|
||||
|
||||
if (!ctx.tx.isFieldPresent(sfEscrowID) &&
|
||||
!ctx.tx.isFieldPresent(sfOfferSequence))
|
||||
return temMALFORMED;
|
||||
|
||||
return preflight2(ctx);
|
||||
}
|
||||
|
||||
@@ -704,13 +720,21 @@ EscrowCancel::doApply()
|
||||
return temDISABLED;
|
||||
|
||||
std::optional<uint256> escrowID = ctx_.tx[~sfEscrowID];
|
||||
std::optional<std::uint32_t> offerSequence = ctx_.tx[~sfOfferSequence];
|
||||
|
||||
if (escrowID && ctx_.tx[sfOfferSequence] != 0)
|
||||
return temMALFORMED;
|
||||
if (!view().rules().enabled(fixXahauV1))
|
||||
{
|
||||
if (escrowID && ctx_.tx[sfOfferSequence] != 0)
|
||||
return temMALFORMED;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (escrowID && offerSequence)
|
||||
return temMALFORMED;
|
||||
}
|
||||
|
||||
Keylet k = escrowID
|
||||
? Keylet(ltESCROW, *escrowID)
|
||||
: keylet::escrow(ctx_.tx[sfOwner], ctx_.tx[sfOfferSequence]);
|
||||
Keylet k = escrowID ? Keylet(ltESCROW, *escrowID)
|
||||
: keylet::escrow(ctx_.tx[sfOwner], *offerSequence);
|
||||
|
||||
auto const slep = ctx_.view().peek(k);
|
||||
if (!slep)
|
||||
|
||||
@@ -710,7 +710,6 @@ Import::preflight(PreflightContext const& ctx)
|
||||
{
|
||||
auto const& data = (*xpop)[jss::validation][jss::data];
|
||||
std::set<std::string> used_key;
|
||||
|
||||
for (const auto& key : data.getMemberNames())
|
||||
{
|
||||
auto nodepub = key;
|
||||
@@ -818,7 +817,17 @@ Import::preflight(PreflightContext const& ctx)
|
||||
<< " validation count: " << validationCount;
|
||||
|
||||
// check if the validation count is adequate
|
||||
if (quorum >= validationCount)
|
||||
auto hasInsufficientQuorum = [&ctx](int quorum, int validationCount) {
|
||||
if (ctx.rules.enabled(fixXahauV1))
|
||||
{
|
||||
return quorum > validationCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
return quorum >= validationCount;
|
||||
}
|
||||
};
|
||||
if (hasInsufficientQuorum(quorum, validationCount))
|
||||
{
|
||||
JLOG(ctx.j.warn()) << "Import: xpop did not contain an 80% quorum for "
|
||||
"the txn it purports to prove. "
|
||||
|
||||
@@ -1856,6 +1856,10 @@ SetHook::setHook()
|
||||
else if (oldHookSLE && !newHooksEmpty)
|
||||
{
|
||||
// UPDATE ltHOOK
|
||||
if (view().rules().enabled(fixXahauV1))
|
||||
{
|
||||
(*newHookSLE)[sfOwnerNode] = (*oldHookSLE)[sfOwnerNode];
|
||||
}
|
||||
view().erase(oldHookSLE);
|
||||
view().insert(newHookSLE);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -130,6 +130,8 @@ ApplyStateTable::generateTxMeta(
|
||||
if (!hookEmission.empty())
|
||||
meta.setHookEmissions(STArray{hookEmission, sfHookEmissions});
|
||||
|
||||
bool const recordDefaultAmounts = to.rules().enabled(fixXahauV1);
|
||||
|
||||
Mods newMod;
|
||||
for (auto& item : items_)
|
||||
{
|
||||
@@ -232,8 +234,12 @@ ApplyStateTable::generateTxMeta(
|
||||
STObject news(sfNewFields);
|
||||
for (auto const& obj : *curNode)
|
||||
{
|
||||
bool const shouldRecord =
|
||||
(obj.getSType() == STI_AMOUNT && recordDefaultAmounts) ||
|
||||
!obj.isDefault();
|
||||
|
||||
// save non-default values
|
||||
if (!obj.isDefault() &&
|
||||
if (shouldRecord &&
|
||||
obj.getFName().shouldMeta(
|
||||
SField::sMD_Create | SField::sMD_Always))
|
||||
news.emplace_back(obj);
|
||||
|
||||
@@ -74,7 +74,7 @@ namespace detail {
|
||||
// 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
|
||||
// the actual number of amendments. A LogicError on startup will verify this.
|
||||
static constexpr std::size_t numFeatures = 66;
|
||||
static constexpr std::size_t numFeatures = 67;
|
||||
|
||||
/** Amendments that this server supports and the default voting behavior.
|
||||
Whether they are enabled depends on the Rules defined in the validated
|
||||
@@ -354,6 +354,7 @@ extern uint256 const featureImport;
|
||||
extern uint256 const featureXahauGenesis;
|
||||
extern uint256 const featureHooksUpdate1;
|
||||
extern uint256 const fixURITokenV1;
|
||||
extern uint256 const fixXahauV1;
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
|
||||
@@ -460,6 +460,7 @@ REGISTER_FEATURE(Import, Supported::yes, VoteBehavior::De
|
||||
REGISTER_FEATURE(XahauGenesis, Supported::yes, VoteBehavior::DefaultYes);
|
||||
REGISTER_FEATURE(HooksUpdate1, Supported::yes, VoteBehavior::DefaultYes);
|
||||
REGISTER_FIX (fixURITokenV1, Supported::yes, VoteBehavior::DefaultNo);
|
||||
REGISTER_FIX (fixXahauV1, Supported::yes, VoteBehavior::DefaultNo);
|
||||
|
||||
|
||||
// The following amendments are obsolete, but must remain supported
|
||||
|
||||
@@ -88,7 +88,7 @@ TxFormats::TxFormats()
|
||||
add(jss::OfferCancel,
|
||||
ttOFFER_CANCEL,
|
||||
{
|
||||
{sfOfferSequence, soeREQUIRED},
|
||||
{sfOfferSequence, soeOPTIONAL},
|
||||
{sfOfferID, soeOPTIONAL}, // keylet as alternative to offerseq
|
||||
{sfTicketSequence, soeOPTIONAL},
|
||||
},
|
||||
@@ -133,7 +133,7 @@ TxFormats::TxFormats()
|
||||
ttESCROW_FINISH,
|
||||
{
|
||||
{sfOwner, soeREQUIRED},
|
||||
{sfOfferSequence, soeREQUIRED},
|
||||
{sfOfferSequence, soeOPTIONAL},
|
||||
{sfEscrowID, soeOPTIONAL}, // keylet as alternative to offerseq
|
||||
{sfFulfillment, soeOPTIONAL},
|
||||
{sfCondition, soeOPTIONAL},
|
||||
@@ -145,7 +145,7 @@ TxFormats::TxFormats()
|
||||
ttESCROW_CANCEL,
|
||||
{
|
||||
{sfOwner, soeREQUIRED},
|
||||
{sfOfferSequence, soeREQUIRED},
|
||||
{sfOfferSequence, soeOPTIONAL},
|
||||
{sfEscrowID, soeOPTIONAL}, // keylet as alternative to offerseq
|
||||
{sfTicketSequence, soeOPTIONAL},
|
||||
},
|
||||
|
||||
+191
-103
@@ -4256,128 +4256,216 @@ struct Escrow_test : public beast::unit_test::suite
|
||||
auto const gw = Account{"gateway"};
|
||||
auto const USD = gw["USD"];
|
||||
|
||||
Env env{*this, features};
|
||||
env.fund(XRP(10000), alice, bob, gw);
|
||||
env.close();
|
||||
env.trust(USD(1000000), alice);
|
||||
env.trust(USD(1000000), bob);
|
||||
env.close();
|
||||
env(pay(gw, alice, USD(10000)));
|
||||
env(pay(gw, bob, USD(10000)));
|
||||
env.close();
|
||||
|
||||
// EscrowCancel - EscrowID
|
||||
for (bool const withXahauV1 : {true, false})
|
||||
{
|
||||
uint256 const escrowId{getEscrowIndex(alice, env.seq(alice))};
|
||||
env(escrow::create(alice, bob, USD(1000)),
|
||||
escrow::finish_time(env.now() + 1s),
|
||||
escrow::cancel_time(env.now() + 2s),
|
||||
fee(1500));
|
||||
auto const amend = withXahauV1 ? features : features - fixXahauV1;
|
||||
Env env{*this, amend};
|
||||
env.fund(XRP(10000), alice, bob, gw);
|
||||
env.close();
|
||||
env.trust(USD(1000000), alice);
|
||||
env.trust(USD(1000000), bob);
|
||||
env.close();
|
||||
env(pay(gw, alice, USD(10000)));
|
||||
env(pay(gw, bob, USD(10000)));
|
||||
env.close();
|
||||
|
||||
env(escrow::cancel(bob, alice, 0),
|
||||
escrow::escrow_id(escrowId),
|
||||
fee(1500));
|
||||
env.close();
|
||||
// EscrowCancel - EscrowID
|
||||
{
|
||||
uint256 const escrowId{getEscrowIndex(alice, env.seq(alice))};
|
||||
env(escrow::create(alice, bob, USD(1000)),
|
||||
escrow::finish_time(env.now() + 1s),
|
||||
escrow::cancel_time(env.now() + 2s),
|
||||
fee(1500));
|
||||
env.close();
|
||||
|
||||
auto const escrowLE = env.le(keylet::unchecked(escrowId));
|
||||
BEAST_EXPECT(!escrowLE);
|
||||
}
|
||||
if (withXahauV1)
|
||||
{
|
||||
// withXahauV1 - no OfferSequence
|
||||
env(escrow::cancel(bob, alice),
|
||||
escrow::escrow_id(escrowId),
|
||||
fee(1500),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
// !withXahauV1 - OfferSequence == 0
|
||||
env(escrow::cancel(bob, alice, 0),
|
||||
escrow::escrow_id(escrowId),
|
||||
fee(1500),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
}
|
||||
|
||||
// EscrowCancel - no EscrowID or OfferSequence
|
||||
{
|
||||
uint256 const escrowId{getEscrowIndex(alice, env.seq(alice))};
|
||||
env(escrow::create(alice, bob, USD(1000)),
|
||||
escrow::finish_time(env.now() + 1s),
|
||||
escrow::cancel_time(env.now() + 2s),
|
||||
fee(1500));
|
||||
env.close();
|
||||
auto const escrowLE = env.le(keylet::unchecked(escrowId));
|
||||
BEAST_EXPECT(!escrowLE);
|
||||
}
|
||||
|
||||
Json::Value jv;
|
||||
jv[jss::TransactionType] = jss::EscrowCancel;
|
||||
jv[jss::Flags] = tfUniversal;
|
||||
jv[jss::Account] = bob.human();
|
||||
jv[sfOwner.jsonName] = alice.human();
|
||||
env(jv, fee(1500), ter(temMALFORMED));
|
||||
env.close();
|
||||
// EscrowCancel - no EscrowID or OfferSequence
|
||||
{
|
||||
uint256 const escrowId{getEscrowIndex(alice, env.seq(alice))};
|
||||
env(escrow::create(alice, bob, USD(1000)),
|
||||
escrow::finish_time(env.now() + 1s),
|
||||
escrow::cancel_time(env.now() + 2s),
|
||||
fee(1500));
|
||||
env.close();
|
||||
|
||||
auto const escrowLE = env.le(keylet::unchecked(escrowId));
|
||||
BEAST_EXPECT(escrowLE);
|
||||
}
|
||||
env(escrow::cancel(bob, alice), fee(1500), ter(temMALFORMED));
|
||||
env.close();
|
||||
|
||||
// EscrowCancel - EscrowID & OfferSequence
|
||||
{
|
||||
uint256 const escrowId{getEscrowIndex(alice, env.seq(alice))};
|
||||
env(escrow::create(alice, bob, USD(1000)),
|
||||
escrow::finish_time(env.now() + 1s),
|
||||
escrow::cancel_time(env.now() + 2s),
|
||||
fee(1500));
|
||||
env.close();
|
||||
auto const escrowLE = env.le(keylet::unchecked(escrowId));
|
||||
BEAST_EXPECT(escrowLE);
|
||||
}
|
||||
|
||||
env(escrow::cancel(bob, alice, 0),
|
||||
escrow::escrow_id(escrowId),
|
||||
fee(1500),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
// EscrowCancel - EscrowID & OfferSequence
|
||||
{
|
||||
uint256 const escrowId{getEscrowIndex(alice, env.seq(alice))};
|
||||
auto const seq = env.seq(alice);
|
||||
env(escrow::create(alice, bob, USD(1000)),
|
||||
escrow::finish_time(env.now() + 1s),
|
||||
escrow::cancel_time(env.now() + 2s),
|
||||
fee(1500));
|
||||
env.close();
|
||||
|
||||
auto const escrowLE = env.le(keylet::unchecked(escrowId));
|
||||
BEAST_EXPECT(!escrowLE);
|
||||
}
|
||||
env(escrow::cancel(bob, alice, seq),
|
||||
escrow::escrow_id(escrowId),
|
||||
fee(1500),
|
||||
ter(temMALFORMED));
|
||||
env.close();
|
||||
|
||||
// EscrowFinish - EscrowID
|
||||
{
|
||||
uint256 const escrowId{getEscrowIndex(alice, env.seq(alice))};
|
||||
env(escrow::create(alice, bob, USD(1000)),
|
||||
escrow::finish_time(env.now() + 1s),
|
||||
fee(1500));
|
||||
env.close(5s);
|
||||
auto const escrowLE = env.le(keylet::unchecked(escrowId));
|
||||
BEAST_EXPECT(escrowLE);
|
||||
}
|
||||
|
||||
env(escrow::finish(bob, alice, 0),
|
||||
escrow::escrow_id(escrowId),
|
||||
fee(1500));
|
||||
env.close();
|
||||
// EscrowCancel - EscrowID & OfferSequence 0
|
||||
{
|
||||
uint256 const escrowId{getEscrowIndex(alice, env.seq(alice))};
|
||||
env(escrow::create(alice, bob, USD(1000)),
|
||||
escrow::finish_time(env.now() + 1s),
|
||||
escrow::cancel_time(env.now() + 2s),
|
||||
fee(1500));
|
||||
env.close();
|
||||
|
||||
auto const escrowLE = env.le(keylet::unchecked(escrowId));
|
||||
BEAST_EXPECT(!escrowLE);
|
||||
}
|
||||
if (withXahauV1)
|
||||
{
|
||||
// withXahauV1 - OfferSequence 0 == temMALFORMED
|
||||
env(escrow::cancel(bob, alice, 0),
|
||||
escrow::escrow_id(escrowId),
|
||||
fee(1500),
|
||||
ter(temMALFORMED));
|
||||
env.close();
|
||||
auto const escrowLE = env.le(keylet::unchecked(escrowId));
|
||||
BEAST_EXPECT(escrowLE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// withXahauV1 - OfferSequence 0 == tesSUCCESS
|
||||
env(escrow::cancel(bob, alice, 0),
|
||||
escrow::escrow_id(escrowId),
|
||||
fee(1500),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
auto const escrowLE = env.le(keylet::unchecked(escrowId));
|
||||
BEAST_EXPECT(!escrowLE);
|
||||
}
|
||||
}
|
||||
|
||||
// EscrowFinish - no EscrowID or OfferSequence
|
||||
{
|
||||
uint256 const escrowId{getEscrowIndex(alice, env.seq(alice))};
|
||||
env(escrow::create(alice, bob, USD(1000)),
|
||||
escrow::finish_time(env.now() + 1s),
|
||||
escrow::cancel_time(env.now() + 2s),
|
||||
fee(1500));
|
||||
env.close();
|
||||
// EscrowFinish - EscrowID
|
||||
{
|
||||
uint256 const escrowId{getEscrowIndex(alice, env.seq(alice))};
|
||||
env(escrow::create(alice, bob, USD(1000)),
|
||||
escrow::finish_time(env.now() + 1s),
|
||||
fee(1500));
|
||||
env.close(5s);
|
||||
|
||||
Json::Value jv;
|
||||
jv[jss::TransactionType] = jss::EscrowFinish;
|
||||
jv[jss::Flags] = tfUniversal;
|
||||
jv[jss::Account] = bob.human();
|
||||
jv[sfOwner.jsonName] = alice.human();
|
||||
env(jv, fee(1500), ter(temMALFORMED));
|
||||
env.close();
|
||||
if (withXahauV1)
|
||||
{
|
||||
// withXahauV1 - no OfferSequence
|
||||
env(escrow::finish(bob, alice),
|
||||
escrow::escrow_id(escrowId),
|
||||
fee(1500),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
// !withXahauV1 - OfferSequence == 0
|
||||
env(escrow::finish(bob, alice, 0),
|
||||
escrow::escrow_id(escrowId),
|
||||
fee(1500),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
}
|
||||
|
||||
auto const escrowLE = env.le(keylet::unchecked(escrowId));
|
||||
BEAST_EXPECT(escrowLE);
|
||||
}
|
||||
auto const escrowLE = env.le(keylet::unchecked(escrowId));
|
||||
BEAST_EXPECT(!escrowLE);
|
||||
}
|
||||
|
||||
// EscrowFinish- EscrowID & OfferSequence
|
||||
{
|
||||
uint256 const escrowId{getEscrowIndex(alice, env.seq(alice))};
|
||||
env(escrow::create(alice, bob, USD(1000)),
|
||||
escrow::finish_time(env.now() + 1s),
|
||||
fee(1500));
|
||||
env.close(5s);
|
||||
// EscrowFinish - no EscrowID or OfferSequence
|
||||
{
|
||||
uint256 const escrowId{getEscrowIndex(alice, env.seq(alice))};
|
||||
env(escrow::create(alice, bob, USD(1000)),
|
||||
escrow::finish_time(env.now() + 1s),
|
||||
fee(1500));
|
||||
env.close();
|
||||
|
||||
env(escrow::finish(bob, alice, 0),
|
||||
escrow::escrow_id(escrowId),
|
||||
fee(1500),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
env(escrow::finish(bob, alice), fee(1500), ter(temMALFORMED));
|
||||
env.close();
|
||||
|
||||
auto const escrowLE = env.le(keylet::unchecked(escrowId));
|
||||
BEAST_EXPECT(!escrowLE);
|
||||
auto const escrowLE = env.le(keylet::unchecked(escrowId));
|
||||
BEAST_EXPECT(escrowLE);
|
||||
}
|
||||
|
||||
// EscrowFinish- EscrowID & OfferSequence
|
||||
{
|
||||
uint256 const escrowId{getEscrowIndex(alice, env.seq(alice))};
|
||||
auto const seq = env.seq(alice);
|
||||
env(escrow::create(alice, bob, USD(1000)),
|
||||
escrow::finish_time(env.now() + 1s),
|
||||
fee(1500));
|
||||
env.close(5s);
|
||||
|
||||
env(escrow::finish(bob, alice, seq),
|
||||
escrow::escrow_id(escrowId),
|
||||
fee(1500),
|
||||
ter(temMALFORMED));
|
||||
env.close();
|
||||
|
||||
auto const escrowLE = env.le(keylet::unchecked(escrowId));
|
||||
BEAST_EXPECT(escrowLE);
|
||||
}
|
||||
|
||||
// EscrowFinish- EscrowID & OfferSequence 0
|
||||
{
|
||||
uint256 const escrowId{getEscrowIndex(alice, env.seq(alice))};
|
||||
env(escrow::create(alice, bob, USD(1000)),
|
||||
escrow::finish_time(env.now() + 1s),
|
||||
fee(1500));
|
||||
env.close(5s);
|
||||
|
||||
if (withXahauV1)
|
||||
{
|
||||
// withXahauV1 - OfferSequence 0 == temMALFORMED
|
||||
env(escrow::finish(bob, alice, 0),
|
||||
escrow::escrow_id(escrowId),
|
||||
fee(1500),
|
||||
ter(temMALFORMED));
|
||||
env.close();
|
||||
auto const escrowLE = env.le(keylet::unchecked(escrowId));
|
||||
BEAST_EXPECT(escrowLE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// !withXahauV1 - OfferSequence 0 == tesSUCCESS
|
||||
env(escrow::finish(bob, alice, 0),
|
||||
escrow::escrow_id(escrowId),
|
||||
fee(1500),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
auto const escrowLE = env.le(keylet::unchecked(escrowId));
|
||||
BEAST_EXPECT(!escrowLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+51
-59
@@ -105,93 +105,85 @@ inline std::string ImportTCAccountSet::max = R"json({
|
||||
})json";
|
||||
inline std::string ImportTCAccountSet::w_seed = R"json({
|
||||
"ledger": {
|
||||
"acroot": "8D612AAAEA2C875978527851BB0727CE64B21D792E91B791FEC769C01410B405",
|
||||
"close": 743212280,
|
||||
"coins": "99999998999999832",
|
||||
"acroot": "3975FE3ACF65A9BCC64F07F49B5AEC93E9176CB8DDFE7B5AEDCDC191EA3A8B8C",
|
||||
"close": 754758421,
|
||||
"coins": "99999998000000000",
|
||||
"cres": 10,
|
||||
"flags": 0,
|
||||
"index": 21,
|
||||
"pclose": 743212272,
|
||||
"phash": "B94C4657B7529C72DDCE970A87E2EB9EE8EE12580ADFE6CF93B8672E4B289BBC",
|
||||
"txroot": "0B7479863581D57CB97867293AA2DD17C2DA4005FC139082925AA5806D956389"
|
||||
"index": 149,
|
||||
"pclose": 754758420,
|
||||
"phash": "8F84F7AB19B38FA4377B34E1234EA613A2A5FE522AF08F0B5E0B957C726A6B15",
|
||||
"txroot": "7B4454B7542F049427CE7A5148BDC385E741F2239C19E71E1CC7E4231A383589"
|
||||
},
|
||||
"transaction": {
|
||||
"blob": "12000322000000002400000014201B00000027201D0000535968400000003B9ACA0073210388935426E0D08083314842EDFBB2D517BD47699F9A4527318A8E10468C97C0527446304402205A21EE95C4EBAAC3BB6E438B86BE0FFF864D7EDAB0827F04621B3C5EB0F84B2002206A025D68D8112C87913F228ED47C7CDFE79E217186056876E3FE60C8D0D7BB5E8114AE123A8556F3CF91154711376AFB0F894F832B3D",
|
||||
"meta": "201C00000002F8E51100612500000014550664762F06918B9DDF5D8933481466D394E8D137DE112C9EFC74AE00F5B1BD0D5692FA6A9FC8EA6018D5D16532D7795C91BFB0831355BDFDA177E86C8BF997985FE624000000146240000002540BE400E1E7220000000024000000152D00000000624000000218711A008114AE123A8556F3CF91154711376AFB0F894F832B3DE1E1F1031000",
|
||||
"blob": "1200032200000000240000007D201B000000A7201D0000535968400000003B9ACA0073210388935426E0D08083314842EDFBB2D517BD47699F9A4527318A8E10468C97C05274473045022100BED5EC411AA84FF23B26D60673C1B42901E253C72DFD92B326DF11B94FAB653D022072B734E038F30D4693A392B1609DEFCE57508F6BB5A3FBD721CC55DDDE929BCD8114AE123A8556F3CF91154711376AFB0F894F832B3D",
|
||||
"meta": "201C00000003F8E5110061250000009555248470440C362FE1DA9C45D43C68583632588F8D5FAACC0038A60F1C292109875692FA6A9FC8EA6018D5D16532D7795C91BFB0831355BDFDA177E86C8BF997985FE6240000007D624000000218711A00E1E72200000000240000007E2D000000016240000001DCD650008114AE123A8556F3CF91154711376AFB0F894F832B3DE1E1F1031000",
|
||||
"proof": {
|
||||
"children": {
|
||||
"0": {
|
||||
"children": {},
|
||||
"hash": "509C0CFF6C808D0A97271FC67C694D95BF177AF4C47D86CD1182516BDDEB6025",
|
||||
"key": "005D3A84B6EF5A5BF673019F4C583E812F2429D2E6524119498803BD4D82B616"
|
||||
"children": {
|
||||
"2": {
|
||||
"children": {},
|
||||
"hash": "B19EFD49679890EA362F3938AFFC6FCC3D4B57AAE0054F42237E51ADEFC00E2A",
|
||||
"key": "02418867190CC2BBA46600E334985E6915C861DBB69E030D2939CFE1FC94D4CC"
|
||||
},
|
||||
"F": {
|
||||
"children": {},
|
||||
"hash": "48E8A4BAE146645DA9FB45AA126676BF94FA767DBE2FEB63D570175C5C6EABF6",
|
||||
"key": "0F84DB191B9B813AC94EC51EA58B69EB5B5C606A69075A64068F911246DFEFD5"
|
||||
}
|
||||
},
|
||||
"hash": "B9AC3B86E69AFE74C4AE62E2E2A82BBBC4578BE84C093A9E5ECF15FD6C85164D",
|
||||
"key": "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
"1": {
|
||||
"children": {},
|
||||
"hash": "7049738FBCD2A02C6424D2D0AED1E686525E72CBEE7E1E46665153D547152BEC",
|
||||
"key": "1B0C515B4719732CA8E192DCE7C853EC9FDCB555044C7DBF6304842D1131B3F8"
|
||||
"hash": "8521D6C26199F9F6D54E9522385C44C52E2E3EF48560AE64D3D089BC268A1311",
|
||||
"key": "1F7D6AC7280BA77EC0676E08111CA9FC552C48DA16662B49A197C2996A594574"
|
||||
},
|
||||
"4": {
|
||||
"2": {
|
||||
"children": {},
|
||||
"hash": "DF2BD3EE2061F7B6BA108AFD2E0879BBC7A416F004EC31721B1E35327AC84CC0",
|
||||
"key": "4636DAF80989AD827DB21924CCA58DA67188569631135A5E04E173B7142E2B4F"
|
||||
"hash": "01404B9BC507C42FC466B3BCC056B544DFEEB51E5C3030F90CC63D092DA9EDFF",
|
||||
"key": "248470440C362FE1DA9C45D43C68583632588F8D5FAACC0038A60F1C29210987"
|
||||
},
|
||||
"5": {
|
||||
"children": {},
|
||||
"hash": "E000CC0736630D66DAB573A2642E1BD0646DFB13A871B2CCFA6E4226F477D88C",
|
||||
"key": "52C1D70065FC14B118011B14B3936FF71D97F9F1D21891BBBD2293B27AC6F8BF"
|
||||
"hash": "8A05CC08E8238765E4B94C14E09C2AD218B81F7FDD0415D6FE7F57B9B626899B",
|
||||
"key": "5BC558F8699A824BE7C09A56E1D0A0FACA6F44F57AB7BC0306C8F1C4870FCE1E"
|
||||
},
|
||||
"7": {
|
||||
"children": {
|
||||
"1": {
|
||||
"children": {},
|
||||
"hash": "4156BB37D4BBA887A646879B3585065B95157FA15A0A68DDCA87CC90B6A8E370",
|
||||
"key": "71C688E6B6B99744C01D908E0C75D12D91090BB109E9E39AC08150A973A90810"
|
||||
},
|
||||
"2": {
|
||||
"children": {},
|
||||
"hash": "EA93162C432C54B8CEDA63184FA9F0ABC76C5CB547671AC4069A8EEF7CE1DD1A",
|
||||
"key": "72092AC8B4A50C6E191650344AFC93FE6EDCD00AD4B7D929A524DCCA7DA06074"
|
||||
}
|
||||
},
|
||||
"hash": "191973AFD8C1667F39C050554AC62D67311CD7DE1E406EE7DF8EB0407930D891",
|
||||
"key": "7000000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
"B": {
|
||||
"children": {
|
||||
"9": {
|
||||
"children": {},
|
||||
"hash": "5109702FDCFFAF311C0AD8E7D4BECE7FA350395A2EAF522A5A7D04337B136B31",
|
||||
"key": "B9448E0093010B019347E2D0BF9C2EB2B8F529877DABFAF7DF4672CFFEC642D8"
|
||||
},
|
||||
"C": {
|
||||
"children": {},
|
||||
"hash": "E80D50B1E6475C8588059C966BBEF247A15D7C8DE0674F0D7122316F9D424BFC",
|
||||
"key": "BCBB6F4F04F0B108630E5CB04E6C9927D2F2621FD83F5548F12D4E44233AC2AA"
|
||||
}
|
||||
},
|
||||
"hash": "01664A1CB97086A0E222BB2FEEE8CD5222E9535064C366CF3DF76A80A17BD7B2",
|
||||
"key": "B000000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
"F": {
|
||||
"C": {
|
||||
"children": {},
|
||||
"hash": "8C26E194C7B44E108EFF98082D19BB2B739C5F8E6BB0C281D9ECEE11F98C3770",
|
||||
"key": "F4DCF93061C61D249A16934AF83C3EFCE51AD98469AFC65B260C2100683CB761"
|
||||
"hash": "652BC7C2C0F3FBA842AD24BB92C9DBFC2ABBB47D11E5255BD10A5BF5A2F12DEF",
|
||||
"key": "C041798921B80DB9F9B017A27514BE6942ED00CDE078E7E7E1C9F011E0DD9B3D"
|
||||
},
|
||||
"D": {
|
||||
"children": {},
|
||||
"hash": "D4772ADC693366E7ADC55437496A80E0073556CCC6F34F28A3CA22F27B8FC804",
|
||||
"key": "D0F5762BD1D415558E1C825A0933E7A0B2AC648AB719CE224E25E6A1EAEFB51D"
|
||||
}
|
||||
},
|
||||
"hash": "0B7479863581D57CB97867293AA2DD17C2DA4005FC139082925AA5806D956389",
|
||||
"hash": "7B4454B7542F049427CE7A5148BDC385E741F2239C19E71E1CC7E4231A383589",
|
||||
"key": "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
}
|
||||
},
|
||||
"validation": {
|
||||
"data": {
|
||||
"n94QWAYxKUHacmyFTnzK4bvqVcUfr6RwtaNxCM2cJRY59UHmz1Fr": "22800000012600000015292C4C84F53A29EC0A36EDAB6C61510AD4F33846A123D86FDAD30CBF175E217BA7B5394A5A761DA5C6B7A45D678DA8501720806024F4F741C65B2E44B005CA293120889A6BC5F1E179335E20384AB3C6D15019B94C4657B7529C72DDCE970A87E2EB9EE8EE12580ADFE6CF93B8672E4B289BBC732103FCA947A7F08B146457BEF95AF0CF7C3ABF0D09CD1DC02099F7185C37BB32807576473045022100BBBE6EDE0B2B61CD369E2188C8FBFACCB35CA2D166FD29D5E3D7B2195083E74302201FAA160136301A43E518B9424A0DA5DC1E7EF8B90DAE2FA87310047498514EB4",
|
||||
"n9KqAeJTJEJaMZNN35SNrPDbs324rwjDPy6BFHjZ4oM4en4snKjf": "22800000012600000015292C4C84F53A434EDA585468FD92510AD4F33846A123D86FDAD30CBF175E217BA7B5394A5A761DA5C6B7A45D678DA8501720806024F4F741C65B2E44B005CA293120889A6BC5F1E179335E20384AB3C6D15019B94C4657B7529C72DDCE970A87E2EB9EE8EE12580ADFE6CF93B8672E4B289BBC732102AB4E3B7C53A4265C51952DD9D2CD2829219CDD4F55F63969E38C5C910F3C5F1C76473045022100A011F2C1F61E78CEF76007BB72CE076255027793052DCF7027B10C0C30BA07AC02202380E5FF8330592C594784C4752736D7177D121763D91795C3AD3FEB7AF3A0B5"
|
||||
"n94J5LCRu9bBWrJiwRWujvuVECVPWbXFcQ2VN38qLD378F5pDSDM": "22800000012600000095292CFCB3163A74499C839A2536F051CAD3AEA30BDAC743D24F91EEF18A03DFB7EDA477194429C9132656ACF85867FA501775530CC549425FB587CBEE269283F976D923CBF68A9AD5C636DE22A96F33FBB350198F84F7AB19B38FA4377B34E1234EA613A2A5FE522AF08F0B5E0B957C726A6B15732103EF7BD71691FE8352670866E018ACD21BE011971500485150AFA1A66DC564667676473045022100CD612D4D66388BC6F5B55C6FC79024419354F7C8F64421E18A2F92F8F12C044E02201E95057C863044378B94BD80D17022CE0FC6FEAF26482FA5C8A02C061BFB0529",
|
||||
"n94M7rLruFgtroHGaxjG81DYKssEfSk5kWK7aiyzcfYKrVVDfZfk": "22800000012600000095292CFCB3163A22A5D454FFFE67CD51CAD3AEA30BDAC743D24F91EEF18A03DFB7EDA477194429C9132656ACF85867FA501775530CC549425FB587CBEE269283F976D923CBF68A9AD5C636DE22A96F33FBB350198F84F7AB19B38FA4377B34E1234EA613A2A5FE522AF08F0B5E0B957C726A6B15732103F5BC074629DFF09DA827417F891FBDCB97B08BF4D4A17715C46D89BF36C8FC2876473045022100E2F7EB279A55545A2241E44BB440A3489612189D7F352FA7756F1C145D707C530220550206F6C48FB16D0C63CE4899BE5DF91DF330BA1CB47BB6310DAD0FC40A1461",
|
||||
"n94U45VGVjD4Gp9aZpuAKJHRF5AJXiARzHmmcR38i4cB3zbHKSWZ": "22800000012600000095292CFCB3163AFC08FE942F7912AF51CAD3AEA30BDAC743D24F91EEF18A03DFB7EDA477194429C9132656ACF85867FA501775530CC549425FB587CBEE269283F976D923CBF68A9AD5C636DE22A96F33FBB350198F84F7AB19B38FA4377B34E1234EA613A2A5FE522AF08F0B5E0B957C726A6B15732103E1177E8CC69B97B21B6C25813CC545BEEA49B03FD668F1701EC29C7FB8E609467647304502210089AD42057DF50C0324F1DC0B4935E124C0C58554369AEE7869E603B8C4AF686102205521AB9889240487CE9ADFE14F5844030D4C2A01B23EF49E53F3C4619A02AF15",
|
||||
"n9KZofcLaHcfujXR4a3E17jKSvyNp8SZHu9rWVjhB9mGFXxB2w4L": "22800000012600000095292CFCB3153ABFAC3C292F2B6FE551CAD3AEA30BDAC743D24F91EEF18A03DFB7EDA477194429C9132656ACF85867FA501775530CC549425FB587CBEE269283F976D923CBF68A9AD5C636DE22A96F33FBB350198F84F7AB19B38FA4377B34E1234EA613A2A5FE522AF08F0B5E0B957C726A6B1573210286A448918DA7F8BF7693552EF9E47AFC57C20D9E090132633D521D32889040C876473045022100D6A52670D463FD1994030A39CEA91E87BA26353B6384FD4218DDA8E3AC8B162E022011295AE9BDDBD41F9489FA3D7E8A36B40D946DC4B39FEA654A77EFEADD112AFA",
|
||||
"n9KjgPCVkmyJdWAVBCVKERdz5Xt6x7dLA1Y7ZqayZzJqVnnG982j": "22800000012600000095292CFCB3173AE187F1490B28C1FA51CAD3AEA30BDAC743D24F91EEF18A03DFB7EDA477194429C9132656ACF85867FA501775530CC549425FB587CBEE269283F976D923CBF68A9AD5C636DE22A96F33FBB350198F84F7AB19B38FA4377B34E1234EA613A2A5FE522AF08F0B5E0B957C726A6B157321029D15B24621B84804E7360DA1CC35F36B8A2771A316A3B83008F85CB370738C2876473045022100A3ECFC40D87E280D7FEDC184BA6DBBE6E77CF6FF08FCF7AE2D4B4FE8CD98B3BF0220726B6A7E9A6AB574EA82A6B5DF628B23C1193A094AF4CC2F28695FFA49CF22BC",
|
||||
"n9L7FECrrDnTTLRJHc7rVxyTsKnjLcQXea5uhTFWxKh3TqnSR2Rz": "22800000012600000095292CFCB3163A89DF43A5821D7C4851CAD3AEA30BDAC743D24F91EEF18A03DFB7EDA477194429C9132656ACF85867FA501775530CC549425FB587CBEE269283F976D923CBF68A9AD5C636DE22A96F33FBB350198F84F7AB19B38FA4377B34E1234EA613A2A5FE522AF08F0B5E0B957C726A6B15732102FF077FE93DDC6626CADE5DB5436B03DC4CE81B0387A2B56C078D5E413FE20DC576473045022100EFFD4EC7B5B003BC5CCF07BE6406EE2A218AA46C0FC51902B801EFBE45C8FB0102200FC2D21E57E785076AA6D2D749F5FBAC9B99FDD9259DD7B8F9EB2D058B434807",
|
||||
"n9LCBA8uJWJ2moif8wbm7SBhuR8uenVgBm7VxKSX4VmzcQH6Mw8j": "22800000012600000095292CFCB3163A6C13F3590B29FCC651CAD3AEA30BDAC743D24F91EEF18A03DFB7EDA477194429C9132656ACF85867FA501775530CC549425FB587CBEE269283F976D923CBF68A9AD5C636DE22A96F33FBB350198F84F7AB19B38FA4377B34E1234EA613A2A5FE522AF08F0B5E0B957C726A6B157321031695B0FB0D95F9C41931F14F49841F44997E76607D1E1D4FC57729F20E6C66397646304402203FAD0DF9CE9AD6A9987229E2AF83E80DACF5D0BFD14CC6ED2036CEAD068BB88002206F50EEA8AF44ACAB94100B0A6061396559D60C1D0E532EEA991F3D6E2B88C4D8",
|
||||
"n9LtFW3Hda5qBS8TUPP9NnNnxUYXbhiWSLaNsGXJKyEkEUiSLvtU": "22800000012600000095292CFCB3163AD3E2E9C72D6F8A9E51CAD3AEA30BDAC743D24F91EEF18A03DFB7EDA477194429C9132656ACF85867FA501775530CC549425FB587CBEE269283F976D923CBF68A9AD5C636DE22A96F33FBB350198F84F7AB19B38FA4377B34E1234EA613A2A5FE522AF08F0B5E0B957C726A6B157321033588B42423B7F797AF19ADDA19470D7F6C5DC384B26D3DA14D859345ADB496247646304402207A5ABA310A90FD46D7BB164172750AE752FA389C697BFACE75CE2E9F2842DC4402200A42A054462531CE381047C7FD47DB8F8AC83963F1E7F3091251437912F9BD06",
|
||||
"n9MNStvsHZxrCYnShytCfKMCXBcq8wJjR6fLTS7L2Q8qoFVNioQ8": "22800000012600000095292CFCB3163AA0E5E217DB17866851CAD3AEA30BDAC743D24F91EEF18A03DFB7EDA477194429C9132656ACF85867FA501775530CC549425FB587CBEE269283F976D923CBF68A9AD5C636DE22A96F33FBB350198F84F7AB19B38FA4377B34E1234EA613A2A5FE522AF08F0B5E0B957C726A6B157321036219BE1721FF5F57EBCB1997EA568BA8BED880ED0CF1FD81F25C888EC8E66D67764630440220467BE8918BBF65D201B705D0C83B0DE347ABC7E9353CEA8AEBE9495BC78AEFC602206FFCB1A2BD08B1F3ED18E3A737C83D9AD6CE20E4B90FF61621650E61F2A7A05A",
|
||||
"n9MTTavZe6EPqqyQ27pJbNWpfHw8ZNspVgznrwx5HWm7cdTjKQie": "22800000012600000095292CFCB3163A3E9A11AB5CFA712751CAD3AEA30BDAC743D24F91EEF18A03DFB7EDA477194429C9132656ACF85867FA501775530CC549425FB587CBEE269283F976D923CBF68A9AD5C636DE22A96F33FBB350198F84F7AB19B38FA4377B34E1234EA613A2A5FE522AF08F0B5E0B957C726A6B157321037FA072E183DC2822AF50EBC43280C9AADF0DFE3BCD57D2CB0DD1179034B07543764730450221008A3D649F423D4B3BB74B4943DD3B4841BA2EF281DC8D1F48C6D3A7E72966344302200C465A03A50F33BD04A9751F4261B96F8058710D18DFC7DCE09850C735FE8B12"
|
||||
},
|
||||
"unl": {
|
||||
"blob": "eyJzZXF1ZW5jZSI6MSwiZXhwaXJhdGlvbiI6NzY3Nzg0NjQ1LCJ2YWxpZGF0b3JzIjpbeyJ2YWxpZGF0aW9uX3B1YmxpY19rZXkiOiJFRDExREMwN0E2REEzRDA3QzAxMkUxOUZGOUFDNjdBQ0U1MzlBMjk1MTQ1QzhEQTM5NjQzN0NBQ0FFQzM2NzA5RjYiLCJtYW5pZmVzdCI6IkpBQUFBQUZ4SWUwUjNBZW0yajBId0JMaG4vbXNaNnpsT2FLVkZGeU5vNVpEZkt5dXcyY0o5bk1oQXF0T08zeFRwQ1pjVVpVdDJkTE5LQ2tobk4xUFZmWTVhZU9NWEpFUFBGOGNka2N3UlFJaEFOYlBEZlZLUzdwSWFqejlOMlFNNEY4Q3hhd1dJcmF0c3QyQjd3ZWR5czFGQWlCR0s3L1YwRDRBMlp2VFJEQlVQb0JLUVhpQk83QUV3ckRiOFlvN2RUSTJTWEFTUU9lQTIrVGdGVlRwNzdlN3VFZGpYNU1BYk8yU0t2dk8zOW1POEFyQkNqemRPUElxVmIrWi9QMDJUTmYzNjUrYjVCOGc3V0xEY0x2VkNpZUxjemw4MHcwPSJ9LHsidmFsaWRhdGlvbl9wdWJsaWNfa2V5IjoiRURBMTY0RjRCMzZDMkQ3MzA0NjJENUY3NjJCRkEyODA4QUE1MDkyQUJDRUNFQkIyNzA4OTUyNUQxRDA1NEJFMzNCIiwibWFuaWZlc3QiOiJKQUFBQUFGeEllMmhaUFN6YkMxekJHTFY5Mksvb29DS3BRa3F2T3pyc25DSlVsMGRCVXZqTzNNaEEveXBSNmZ3aXhSa1Y3NzVXdkRQZkRxL0RRbk5IY0FnbWZjWVhEZTdNb0IxZGtjd1JRSWhBTjRldTFvSGV0bFVDUmZmZ2FaeTkvTWJrQ0prWlFZdlJoMFVJZWFCaVZodkFpQWhGWXZKTXBPeVFpNGxFdzdzM0pTVTBMRm5FckRWVlRnK3NYUVk0c3Zta25BU1FCSGswakIweG1yL1UwbnkyajNrRmVvdEJUVEExVzdXcHBKbXFvYmR4SXkyR0w0QXBRaEpPcm5aRy93bXZqeFJCNXV4Y05FNUdUR1NZekQ3azhhVEx3bz0ifV19",
|
||||
"blob": "eyJzZXF1ZW5jZSI6MSwiZXhwaXJhdGlvbiI6NzU3MzQ5NjI0LCJ2YWxpZGF0b3JzIjpbeyJ2YWxpZGF0aW9uX3B1YmxpY19rZXkiOiJFREJBOUZGMzEzNjgyMzlGNDIxRjA0QkY2ODEzQkJGNzZDNkJCRDQ1NkMyRTEyNDg2MDY2MjdCOTkwRjA5MTc2ODkiLCJtYW5pZmVzdCI6IkpBQUFBRVJ4SWUyNm4vTVRhQ09mUWg4RXYyZ1R1L2RzYTcxRmJDNFNTR0JtSjdtUThKRjJpWE1oQTMrZ2N1R0QzQ2dpcjFEcnhES0F5YXJmRGY0N3pWZlN5dzNSRjVBMHNIVkRka1l3UkFJZ2J4bVdKWXoxMFI2RVh6OG1RRmxKazlMM1UwZkQxT2UzbDJYK3NVOGFqajBDSUNIb2RoNzRWaDJNL0oxRnlzS2NOUmp1YWpKaCtSN1dqeXVBNHFqWWwvSHVkeDEwWlhOMExYSnBjSEJzWlM1MmJtOWtaVEV1ZEhKaGJuTnBZUzVqYjNBU1FEcDJuUVVTbk9CYlVxMHpCU05wMzRhRktBWnRrWHRaS3BjejBlQitEVG12TXRGN3M0Y240ZW8veHhkZU5UbmxJK1FRVmloZUpLSkZKQlJ3NzZwdXdROD0ifSx7InZhbGlkYXRpb25fcHVibGljX2tleSI6IkVEQkJDRDNGRjdGRkVGOTc3REU0Mzg0QUMzODE0NTMwNEM1MUI5MTJDRUYxMTgwNjBGMzQzMTBGRjgwN0NDRUU3QiIsIm1hbmlmZXN0IjoiSkFBQUFEeHhJZTI3elQvMy8rK1hmZVE0U3NPQlJUQk1VYmtTenZFWUJnODBNUS80Qjh6dWUzTWhBMkladmhjaC8xOVg2OHNabCtwV2k2aSsySUR0RFBIOWdmSmNpSTdJNW0xbmRrY3dSUUloQUtMWnFVYjIyYWg0YmJzL3JtTU1VQjl4MXE3MDY0RzczcW5uSytmaU9UVHZBaUFNdUJ4QVFlcEw4a2owRVVlY3ZIT2dKOEo2TUFUdS9CVnFXVzk1alhRNUMzY2RkR1Z6ZEMxeWFYQndiR1V1ZG01dlpHVXlMblJ5WVc1emFXRXVZMjl3RWtCcXpTMmFmdm9XUGJOcWM2UGRxaGV4ZnNUVDBEdUJZd2ltN0c4Y0xvSzg1bktTTW1TQy9ZaGw1cXRTRzkzNWZnQUlqVm9YZXMrZS9Kd3FFU01xZ2ZZQiJ9LHsidmFsaWRhdGlvbl9wdWJsaWNfa2V5IjoiRUQ2N0ZFMkU1MTc1Njc2NjBCMTU0NUEzQjg0OUU2OThERTg5Q0Y4MTUxODg2MjIwMzAxNzc2OEUxMjJBMTM3N0JDIiwibWFuaWZlc3QiOiJKQUFBQUR4eEllMW4vaTVSZFdkbUN4VkZvN2hKNXBqZWljK0JVWWhpSURBWGRvNFNLaE4zdkhNaEEvVzhCMFlwMy9DZHFDZEJmNGtmdmN1WHNJdjAxS0YzRmNSdGliODJ5UHdvZGtZd1JBSWdZV3NQMVMwYzhvZkFlRWp1WjJ3a2NpM29idStLV0tuOWxqMmVqOEJ1YmxVQ0lHTGl2UmJxazRHUW9VWVk2bC9NS0hpeWkwbzBwbmtpSTFLRDV2UHRYRHRnZHgxMFpYTjBMWEpwY0hCc1pTNTJibTlrWlRNdWRISmhibk5wWVM1amIzQVNRSzdZZUtoYnQwNlc1QnpQODk1V09NT1p2SlJLakhaVGdtN0VqYUtjakNLRTQwWTQwaTczeTUreVFHQWpISFlrRGgydE5UdVExQ09HT1E2b2N1VEFpZ1U9In0seyJ2YWxpZGF0aW9uX3B1YmxpY19rZXkiOiJFRDc1OUJFRTREQzIxQzVBMDYzMEZCODdENDJFQ0MzRDk1OUE3RkI0QkY0RUM3RkYxMkRDOUZDQjFCNkFCNDE5MTUiLCJtYW5pZmVzdCI6IkpBQUFBRHB4SWUxMW0rNU53aHhhQmpEN2g5UXV6RDJWbW4rMHYwN0gveExjbjhzYmFyUVpGWE1oQW9ha1NKR05wL2kvZHBOVkx2bmtldnhYd2cyZUNRRXlZejFTSFRLSWtFRElka1l3UkFJZ0JUTHFROXFna3VrVzFwYTBwQ0xRVld2QnFua09NVkVPK3JQTEVoL2praHdDSUZsQURXb3RLc0JBQ0hyWW1EY3N0dXczYjRkdWV4V3dXY0FCdTdkNmR1T3FkeDEwWlhOMExYSnBjSEJzWlM1MmJtOWtaVFF1ZEhKaGJuTnBZUzVqYjNBU1FBN0UrdHVzMHZ0aDk4eGQwWVdLb2FVOVJTL1VUZVQ1RUcwSURzbW9NVHdrN014VTRGVktTL0dXOTUrMHJ0cG0xV0NYM1VRWThaN1pIZmtGMVlxenZRUT0ifSx7InZhbGlkYXRpb25fcHVibGljX2tleSI6IkVEMTFDQzhEQUZDREUxMTFGRDFCNTM4OUJFRDM1QjcwNkQzMUQwMDRGMjBGQUNERjEwQ0RGMTI2MjhDRkE0NUQ2RSIsIm1hbmlmZXN0IjoiSkFBQUFEcHhJZTBSekkydnplRVIvUnRUaWI3VFczQnRNZEFFOGcrczN4RE44U1lvejZSZGJuTWhBdjhIZitrOTNHWW15dDVkdFVOckE5eE02QnNEaDZLMWJBZU5Ya0UvNGczRmRrWXdSQUlnRS84cTI2R0lSaDlLd1ZvUjFLZVBnS3VGcUlyRjV5NnMrREUvaXNmWHJpSUNJR3hQdHZSUjNLZFI3d2haMzI3VXFpUXFvZnM3d2VVRzQ0dEpiZnhZWndCV2R4MTBaWE4wTFhKcGNIQnNaUzUyYm05a1pUVXVkSEpoYm5OcFlTNWpiM0FTUU5hRFNNSmdpU2kxNzRoazYrdnlBRlhzdUFYZkw0YnRFT3c5OVBSSVJwQVAvUGxRa1ZmMXpNdUJrLzJGNzdqai9BTzFnd09va3hjbEJHRmF5MC9jcGc4PSJ9LHsidmFsaWRhdGlvbl9wdWJsaWNfa2V5IjoiRUQ5MjI5NDFEMjQwMEM4M0I3QjU1QzE4QkZFRDRCNzA5QkI4QzAxRkNGMEE3RTlCRTQ5RTA5RDBCOUIyNTRDRTU1IiwibWFuaWZlc3QiOiJKQUFBQURweEllMlNLVUhTUUF5RHQ3VmNHTC90UzNDYnVNQWZ6d3ArbStTZUNkQzVzbFRPVlhNaEF4YVZzUHNObGZuRUdUSHhUMG1FSDBTWmZuWmdmUjRkVDhWM0tmSU9iR1k1ZGtjd1JRSWhBUDBkOHRSZ0JlczNmKzl5Y2Y4c0FNdEdLcnUxN05neGN2azJpRXJQTks5MUFpQTI5WFM4VzNYYVZ4bS9xS0pmSzc0T1JTVlJFL3MzUmFZbGJhMmZoT3JCTDNjZGRHVnpkQzF5YVhCd2JHVXVkbTV2WkdVMkxuUnlZVzV6YVdFdVkyOXdFa0F6V2RkcGxHMkVKUmo2c1ZabEdxTFN6RWhqWEQ3VXFKV1pNSC9IMUZKaW9sWFVBbk5VOXVidjRsWDE0WVFlWmpJbitLR2gwekoxek5KS2YvbGhsRnNKIn0seyJ2YWxpZGF0aW9uX3B1YmxpY19rZXkiOiJFRDY1OThGNjYzRTNDRjQwRDczREMxOUU4NzUwRUQ2N0I4NjAzNTREQjhGMkEzMTVENUZFN0REMDY1MkY0OUQyMUUiLCJtYW5pZmVzdCI6IkpBQUFBRHB4SWUxbG1QWmo0ODlBMXozQm5vZFE3V2U0WURWTnVQS2pGZFgrZmRCbEwwblNIbk1oQSs5NzF4YVIvb05TWndobTRCaXMwaHZnRVpjVkFFaFJVSytocG0zRlpHWjJka1l3UkFJZ1VKbmg3VTNQV3U5LzVKblFBcFpOdmRZanhFTmZkcHIzcFUwY05NZHJ1eXdDSUVLVG5XSzB4RnM0UWVIMFhFZkNSQTFJdjQrMlJzSFhJZHZyR0I3NlVxSmdkeDEwWlhOMExYSnBjSEJzWlM1MmJtOWtaVGN1ZEhKaGJuTnBZUzVqYjNBU1FOakRvVTRjL2ZkbDJONCtFbnR0TXBQeTV5QlhqRldEbXVYZThrZ0FTaERaZllpVGNYZU5LT3RzU2xzQW5PVGIxbllzZzdFbFZpZTB6bGM5dTdQTWVBRT0ifSx7InZhbGlkYXRpb25fcHVibGljX2tleSI6IkVEOTk5RkZGRUY1MUQ3MTJEN0Q0MjVCQTA4M0U3OUU2MDJGNzhBNDkyMDU0QThDMjM4RjRBOTQ0ODc2OTlFRDkwNyIsIm1hbmlmZXN0IjoiSkFBQUFEcHhJZTJabi8vdlVkY1MxOVFsdWdnK2VlWUM5NHBKSUZTb3dqajBxVVNIYVo3WkIzTWhBeldJdENRanQvZVhyeG10MmhsSERYOXNYY09Fc20wOW9VMkZrMFd0dEpZa2RrY3dSUUloQU9RMFRhbFlVYnE3aml0T2MybXMxQm5wUTdsWHJVc2x2WEJSbS9tRG1UZEVBaUE0KzdPSmhkN0pFSlV2QUhSYjByaG5GSkd3b3ZoWWNQNjBBTG81Zm8xaTJIY2RkR1Z6ZEMxeWFYQndiR1V1ZG01dlpHVTRMblJ5WVc1emFXRXVZMjl3RWtBVzR2TlRPMEU5ZEptRC93eFNmcG9qN0V6bUxMV1pFN1dTeWZuTFk0WTBTVEVLR09jK0FGZ251Ty9IekhhdnQ3aTJBUHJkckZhT3IySm1Zb2lIa1RVSiJ9LHsidmFsaWRhdGlvbl9wdWJsaWNfa2V5IjoiRURGNjVFNTAwNkE1M0FGNzU2MTdFQUUyOUM3MzNDNUYzNDFBOTQxNzNDMjkyM0Y2MjY5Mjk2M0QxQTJGMTQwNzYyIiwibWFuaWZlc3QiOiJKQUFBQURweEllMzJYbEFHcFRyM1ZoZnE0cHh6UEY4MEdwUVhQQ2tqOWlhU2xqMGFMeFFIWW5NaEFwMFZza1lodUVnRTV6WU5vY3cxODJ1S0ozR2Line truncated
|
||||
"manifest": "JAAAAAFxIe101ANsZZGkvfnFTO+jm5lqXc5fhtEf2hh0SBzp1aHNwXMh7TN9+b62cZqTngaFYU5tbGpYHC8oYuI3G3vwj9OW2Z9gdkAnUjfY5zOEkhq31tU4338jcyUpVA5/VTsANFce7unDo+JeVoEhfuOb/Y8WA3Diu9XzuOD4U/ikfgf9SZOlOGcBcBJAw44PLjH+HUtEnwX45lIRmo0x5aINFMvZsBpE9QteSDBXKwYzLdnSW4e1bs21o+IILJIiIKU/+1Uxx0FRpQbMDA==",
|
||||
"public_key": "ED74D4036C6591A4BDF9C54CEFA39B996A5DCE5F86D11FDA1874481CE9D5A1CDC1",
|
||||
"signature": "77809A0938EA47F3A03BA0B71DD2C6879416F06574F6B5DC0041C9D806D3D5971282EF99D9EF911F8F37B56DA7016679744EF042C7A98ED425EFFFC6CC8AEA05",
|
||||
"signature": "B7619B4AD763E7E59715C8710E1836558F9B0B3F216F30A7922CCE288434AFDA8C12993D716CE750E603F8A6B21EFB53448758F2D90F3FE5DFD1063350F7040C",
|
||||
"version": 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1682,6 +1682,36 @@ class Import_test : public beast::unit_test::suite
|
||||
ter(temDISABLED));
|
||||
}
|
||||
|
||||
// temMALFORMED - Import: xpop did not contain an 80% quorum for the txn
|
||||
// it purports to prove.
|
||||
for (bool const withXahauV1 : {true, false})
|
||||
{
|
||||
auto const amend = withXahauV1 ? features : features - fixXahauV1;
|
||||
test::jtx::Env env{
|
||||
*this, network::makeNetworkVLConfig(21337, keys), amend};
|
||||
|
||||
auto const alice = Account("alice");
|
||||
env.fund(XRP(1000), alice);
|
||||
env.close();
|
||||
|
||||
Json::Value tmpXpop = import::loadXpop(ImportTCAccountSet::w_seed);
|
||||
Json::Value valData = tmpXpop[jss::validation][jss::data];
|
||||
valData["n9MNStvsHZxrCYnShytCfKMCXBcq8wJjR6fLTS7L2Q8qoFVNioQ8"] =
|
||||
"";
|
||||
valData["n9MTTavZe6EPqqyQ27pJbNWpfHw8ZNspVgznrwx5HWm7cdTjKQie"] =
|
||||
"";
|
||||
if (withXahauV1)
|
||||
{
|
||||
valData
|
||||
["n94J5LCRu9bBWrJiwRWujvuVECVPWbXFcQ2VN38qLD378F5pDSDM"] =
|
||||
"";
|
||||
}
|
||||
tmpXpop[jss::validation][jss::data] = valData;
|
||||
auto const txResult =
|
||||
withXahauV1 ? ter(temMALFORMED) : ter(temMALFORMED);
|
||||
env(import::import(alice, tmpXpop), txResult);
|
||||
}
|
||||
|
||||
test::jtx::Env env{*this, network::makeNetworkVLConfig(21337, keys)};
|
||||
|
||||
auto const feeDrops = env.current()->fees().base;
|
||||
@@ -2573,19 +2603,6 @@ class Import_test : public beast::unit_test::suite
|
||||
// parsed
|
||||
// DA: Catch All
|
||||
|
||||
// temMALFORMED - Import: xpop did not contain an 80% quorum for the txn
|
||||
// it purports to prove.
|
||||
{
|
||||
Json::Value tmpXpop = import::loadXpop(ImportTCAccountSet::w_seed);
|
||||
Json::Value valData;
|
||||
valData["n94at1vSdHSBEun25yT4ZfgqD1tVQNsx1nqRZG3T6ygbuvwgcMZN"] =
|
||||
"";
|
||||
valData["n9KXYzdZD8YpsNiChtMjP6yhvQAhkkh5XeSTbvYyV1waF8wkNnBT"] =
|
||||
"";
|
||||
tmpXpop[jss::validation][jss::data] = valData;
|
||||
env(import::import(alice, tmpXpop), ter(temMALFORMED));
|
||||
}
|
||||
|
||||
// temMALFORMED - Import: xpop inner txn did not contain a sequence
|
||||
// number or fee No Sequence
|
||||
{
|
||||
|
||||
+129
-68
@@ -5113,10 +5113,11 @@ public:
|
||||
|
||||
using namespace jtx;
|
||||
|
||||
// OfferCreate - OfferID
|
||||
// OfferCreate
|
||||
for (bool const withXahauV1 : {true, false})
|
||||
{
|
||||
Env env{*this, features};
|
||||
|
||||
auto const amend = withXahauV1 ? features : features - fixXahauV1;
|
||||
Env env{*this, amend};
|
||||
auto const gw = Account{"gateway"};
|
||||
auto const alice = Account{"alice"};
|
||||
auto const USD = gw["USD"];
|
||||
@@ -5130,58 +5131,80 @@ public:
|
||||
env(pay(gw, alice, USD(200)));
|
||||
env.close();
|
||||
|
||||
uint256 const offerId{getOfferIndex(alice, env.seq(alice))};
|
||||
env(offer(alice, XRP(50), USD(50)));
|
||||
env.close();
|
||||
// sequence id - no offer id
|
||||
{
|
||||
std::uint32_t const offerSeqId{env.seq(alice)};
|
||||
env(offer(alice, XRP(50), USD(50)));
|
||||
env.close();
|
||||
|
||||
auto offers = sortedOffersOnAccount(env, alice);
|
||||
BEAST_EXPECT(offers.size() == 1);
|
||||
auto tx = offer(alice, XRP(50), USD(50));
|
||||
tx[sfOfferSequence.jsonName] = offerSeqId;
|
||||
env(tx, ter(tesSUCCESS));
|
||||
env.close();
|
||||
auto const offerLE = env.le(keylet::offer(alice, offerSeqId));
|
||||
BEAST_EXPECT(!offerLE);
|
||||
}
|
||||
|
||||
auto tx = offer(alice, XRP(50), USD(50));
|
||||
tx[sfOfferID.jsonName] = to_string(offerId);
|
||||
env(tx, ter(tesSUCCESS));
|
||||
env.close();
|
||||
// no sequence id - offer id
|
||||
{
|
||||
uint256 const offerId{getOfferIndex(alice, env.seq(alice))};
|
||||
env(offer(alice, XRP(50), USD(50)));
|
||||
env.close();
|
||||
|
||||
offers = sortedOffersOnAccount(env, alice);
|
||||
BEAST_EXPECT(offers.size() == 1);
|
||||
}
|
||||
auto tx = offer(alice, XRP(50), USD(50));
|
||||
env(tx, offer_id(offerId), ter(tesSUCCESS));
|
||||
env.close();
|
||||
auto const offerLE = env.le(keylet::unchecked(offerId));
|
||||
BEAST_EXPECT(!offerLE);
|
||||
}
|
||||
|
||||
// OfferCreate - OfferSequence
|
||||
{
|
||||
Env env{*this, features};
|
||||
auto const gw = Account{"gateway"};
|
||||
auto const alice = Account{"alice"};
|
||||
auto const USD = gw["USD"];
|
||||
// no offer id or offer sequence
|
||||
{
|
||||
uint256 const offerId{getOfferIndex(alice, env.seq(alice))};
|
||||
env(offer(alice, XRP(50), USD(50)));
|
||||
env.close();
|
||||
|
||||
env.fund(XRP(10000), gw, alice);
|
||||
env.close();
|
||||
env(offer(alice, XRP(50), USD(50)));
|
||||
env.close();
|
||||
auto const offerLE = env.le(keylet::unchecked(offerId));
|
||||
BEAST_EXPECT(offerLE);
|
||||
}
|
||||
|
||||
env(trust(alice, USD(1000)));
|
||||
env.close();
|
||||
// offer id and offer sequence
|
||||
{
|
||||
uint256 const offerId{getOfferIndex(alice, env.seq(alice))};
|
||||
std::uint32_t const offerSeqId{env.seq(alice)};
|
||||
env(offer(alice, XRP(50), USD(50)));
|
||||
env.close();
|
||||
|
||||
env(pay(gw, alice, USD(200)));
|
||||
env.close();
|
||||
auto tx = offer(alice, XRP(50), USD(50));
|
||||
tx[sfOfferSequence.jsonName] = offerSeqId;
|
||||
env(tx, offer_id(offerId), ter(temBAD_SEQUENCE));
|
||||
env.close();
|
||||
auto const offerLE = env.le(keylet::unchecked(offerId));
|
||||
BEAST_EXPECT(offerLE);
|
||||
}
|
||||
|
||||
// OfferCreate - OfferID
|
||||
std::uint32_t const offerSeqId{env.seq(alice)};
|
||||
env(offer(alice, XRP(50), USD(50)));
|
||||
env.close();
|
||||
// offer id and offer sequence 0
|
||||
{
|
||||
uint256 const offerId{getOfferIndex(alice, env.seq(alice))};
|
||||
env(offer(alice, XRP(50), USD(50)));
|
||||
env.close();
|
||||
|
||||
auto offers = sortedOffersOnAccount(env, alice);
|
||||
BEAST_EXPECT(offers.size() == 1);
|
||||
|
||||
auto tx = offer(alice, XRP(50), USD(50));
|
||||
tx[sfOfferSequence.jsonName] = offerSeqId;
|
||||
env(tx, ter(tesSUCCESS));
|
||||
env.close();
|
||||
|
||||
offers = sortedOffersOnAccount(env, alice);
|
||||
BEAST_EXPECT(offers.size() == 1);
|
||||
auto tx = offer(alice, XRP(50), USD(50));
|
||||
tx[sfOfferSequence.jsonName] = 0;
|
||||
env(tx, offer_id(offerId), ter(temBAD_SEQUENCE));
|
||||
env.close();
|
||||
auto const offerLE = env.le(keylet::unchecked(offerId));
|
||||
BEAST_EXPECT(offerLE);
|
||||
}
|
||||
}
|
||||
|
||||
// OfferCancel
|
||||
for (bool const withXahauV1 : {true, false})
|
||||
{
|
||||
Env env{*this, features};
|
||||
auto const amend = withXahauV1 ? features : features - fixXahauV1;
|
||||
Env env{*this, amend};
|
||||
auto const gw = Account{"gateway"};
|
||||
auto const alice = Account{"alice"};
|
||||
auto const USD = gw["USD"];
|
||||
@@ -5203,36 +5226,46 @@ public:
|
||||
|
||||
env(offer_cancel(alice, offerSeqId), ter(tesSUCCESS));
|
||||
env.close();
|
||||
auto const offers = sortedOffersOnAccount(env, alice);
|
||||
BEAST_EXPECT(offers.size() == 0);
|
||||
auto const offerLE = env.le(keylet::offer(alice, offerSeqId));
|
||||
BEAST_EXPECT(!offerLE);
|
||||
}
|
||||
|
||||
// offer id (offer sequence required)
|
||||
// no sequence id - offer id
|
||||
{
|
||||
uint256 const offerId{getOfferIndex(alice, env.seq(alice))};
|
||||
env(offer(alice, XRP(50), USD(50)));
|
||||
env.close();
|
||||
|
||||
env(offer_cancel(alice, 0),
|
||||
offer_id(offerId),
|
||||
ter(temBAD_SEQUENCE));
|
||||
env.close();
|
||||
auto const offers = sortedOffersOnAccount(env, alice);
|
||||
BEAST_EXPECT(offers.size() == 1);
|
||||
if (withXahauV1)
|
||||
{
|
||||
env(offer_cancel(alice),
|
||||
offer_id(offerId),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
auto const offerLE = env.le(keylet::unchecked(offerId));
|
||||
BEAST_EXPECT(!offerLE);
|
||||
}
|
||||
else
|
||||
{
|
||||
env(offer_cancel(alice),
|
||||
offer_id(offerId),
|
||||
ter(temBAD_SEQUENCE));
|
||||
env.close();
|
||||
auto const offerLE = env.le(keylet::unchecked(offerId));
|
||||
BEAST_EXPECT(offerLE);
|
||||
}
|
||||
}
|
||||
|
||||
// no offer id or offer sequence
|
||||
{
|
||||
uint256 const offerId{getOfferIndex(alice, env.seq(alice))};
|
||||
env(offer(alice, XRP(50), USD(50)));
|
||||
env.close();
|
||||
|
||||
Json::Value jv;
|
||||
jv[jss::Account] = alice.human();
|
||||
jv[jss::TransactionType] = jss::OfferCancel;
|
||||
env(jv, ter(temMALFORMED));
|
||||
env(offer_cancel(alice), ter(temBAD_SEQUENCE));
|
||||
env.close();
|
||||
auto const offers = sortedOffersOnAccount(env, alice);
|
||||
BEAST_EXPECT(offers.size() == 2);
|
||||
auto const offerLE = env.le(keylet::unchecked(offerId));
|
||||
BEAST_EXPECT(offerLE);
|
||||
}
|
||||
|
||||
// both offer id and offer sequence
|
||||
@@ -5242,12 +5275,39 @@ public:
|
||||
env(offer(alice, XRP(50), USD(50)));
|
||||
env.close();
|
||||
|
||||
env(offer_cancel(alice, offerSeqId),
|
||||
offer_id(offerId),
|
||||
ter(tesSUCCESS));
|
||||
if (withXahauV1)
|
||||
{
|
||||
env(offer_cancel(alice, offerSeqId),
|
||||
offer_id(offerId),
|
||||
ter(temBAD_SEQUENCE));
|
||||
env.close();
|
||||
auto const offerLE = env.le(keylet::unchecked(offerId));
|
||||
BEAST_EXPECT(offerLE);
|
||||
}
|
||||
else
|
||||
{
|
||||
env(offer_cancel(alice, offerSeqId),
|
||||
offer_id(offerId),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
auto const offerLE = env.le(keylet::unchecked(offerId));
|
||||
BEAST_EXPECT(!offerLE);
|
||||
}
|
||||
}
|
||||
|
||||
// both offer id and offer sequence 0
|
||||
{
|
||||
uint256 const offerId{getOfferIndex(alice, env.seq(alice))};
|
||||
std::uint32_t const offerSeqId{env.seq(alice)};
|
||||
env(offer(alice, XRP(50), USD(50)));
|
||||
env.close();
|
||||
auto const offers = sortedOffersOnAccount(env, alice);
|
||||
BEAST_EXPECT(offers.size() == 2);
|
||||
|
||||
env(offer_cancel(alice, 0),
|
||||
offer_id(offerId),
|
||||
ter(temBAD_SEQUENCE));
|
||||
env.close();
|
||||
auto const offerLE = env.le(keylet::unchecked(offerId));
|
||||
BEAST_EXPECT(offerLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5344,12 +5404,13 @@ public:
|
||||
FeatureBitset const rmSmallIncreasedQOffers{fixRmSmallIncreasedQOffers};
|
||||
FeatureBitset const immediateOfferKilled{featureImmediateOfferKilled};
|
||||
|
||||
testAll(all - takerDryOffer - immediateOfferKilled);
|
||||
testAll(all - flowCross - takerDryOffer - immediateOfferKilled);
|
||||
testAll(all - flowCross - immediateOfferKilled);
|
||||
testAll(all - rmSmallIncreasedQOffers - immediateOfferKilled);
|
||||
testAll(all);
|
||||
testFalseAssert();
|
||||
// testAll(all - takerDryOffer - immediateOfferKilled);
|
||||
// testAll(all - flowCross - takerDryOffer - immediateOfferKilled);
|
||||
// testAll(all - flowCross - immediateOfferKilled);
|
||||
// testAll(all - rmSmallIncreasedQOffers - immediateOfferKilled);
|
||||
// testAll(all);
|
||||
// testFalseAssert();
|
||||
testOfferID(all);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+337
-312
File diff suppressed because it is too large.
Load diff
@@ -89,6 +89,67 @@ public:
|
||||
// fee unit tests, the rest of the time we want to ignore it.
|
||||
#define HSFEE fee(100'000'000)
|
||||
#define M(m) memo(m, "", "")
|
||||
void
|
||||
testHooksOwnerDir()
|
||||
{
|
||||
testcase("Test owner directory");
|
||||
|
||||
using namespace jtx;
|
||||
|
||||
for (bool const withXahauV1 : {true, false})
|
||||
{
|
||||
auto const amend = withXahauV1
|
||||
? supported_amendments()
|
||||
: supported_amendments() - fixXahauV1;
|
||||
|
||||
Env env{*this, amend};
|
||||
|
||||
auto const alice = Account{"alice"};
|
||||
auto const gw = Account{"gateway"};
|
||||
auto const USD = gw["USD"];
|
||||
env.fund(XRP(10000), alice, gw);
|
||||
env.close();
|
||||
env.trust(USD(100000), alice);
|
||||
env.close();
|
||||
env(pay(gw, alice, USD(10000)));
|
||||
|
||||
for (int i = 1; i < 34; ++i)
|
||||
{
|
||||
std::string const uri(i, '?');
|
||||
env(uritoken::mint(alice, uri));
|
||||
}
|
||||
env.close();
|
||||
|
||||
env(ripple::test::jtx::hook(
|
||||
alice, {{hso(accept_wasm, overrideFlag)}}, 0),
|
||||
HSFEE,
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
|
||||
env(ripple::test::jtx::hook(
|
||||
alice, {{hso(accept_wasm, overrideFlag)}}, 0),
|
||||
HSFEE,
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
|
||||
// delete hook
|
||||
Json::Value jv;
|
||||
jv[jss::Account] = alice.human();
|
||||
jv[jss::TransactionType] = jss::SetHook;
|
||||
jv[jss::Flags] = 0;
|
||||
jv[jss::Hooks] = Json::Value{Json::arrayValue};
|
||||
Json::Value iv;
|
||||
iv[jss::Flags] = 1;
|
||||
iv[jss::CreateCode] = "";
|
||||
jv[jss::Hooks][0U][jss::Hook] = iv;
|
||||
|
||||
auto const txResult =
|
||||
withXahauV1 ? ter(tesSUCCESS) : ter(tefBAD_LEDGER);
|
||||
env(jv, HSFEE, txResult);
|
||||
env.close();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testHooksDisabled()
|
||||
{
|
||||
@@ -100,7 +161,8 @@ public:
|
||||
|
||||
// RH TODO: does it matter that passing malformed txn here gives back
|
||||
// temMALFORMED (and not disabled)?
|
||||
env(ripple::test::jtx::hook(alice, {{hso(accept_wasm)}}, 0),
|
||||
env(ripple::test::jtx::hook(
|
||||
alice, {{hso(accept_wasm, overrideFlag)}}, 0),
|
||||
M("Hooks Disabled"),
|
||||
HSFEE,
|
||||
ter(temDISABLED));
|
||||
@@ -7764,6 +7826,134 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test_state_foreign_set_max()
|
||||
{
|
||||
testcase("Test state_foreign_set max");
|
||||
using namespace jtx;
|
||||
|
||||
static const std::vector<uint8_t> ns_maxHook = {
|
||||
0x00U, 0x61U, 0x73U, 0x6dU, 0x01U, 0x00U, 0x00U, 0x00U, 0x01U,
|
||||
0x36U, 0x07U, 0x60U, 0x02U, 0x7fU, 0x7fU, 0x01U, 0x7fU, 0x60U,
|
||||
0x02U, 0x7fU, 0x7fU, 0x01U, 0x7eU, 0x60U, 0x03U, 0x7fU, 0x7fU,
|
||||
0x7eU, 0x01U, 0x7eU, 0x60U, 0x04U, 0x7fU, 0x7fU, 0x7fU, 0x7fU,
|
||||
0x01U, 0x7eU, 0x60U, 0x05U, 0x7fU, 0x7fU, 0x7fU, 0x7fU, 0x7fU,
|
||||
0x01U, 0x7eU, 0x60U, 0x08U, 0x7fU, 0x7fU, 0x7fU, 0x7fU, 0x7fU,
|
||||
0x7fU, 0x7fU, 0x7fU, 0x01U, 0x7eU, 0x60U, 0x01U, 0x7fU, 0x01U,
|
||||
0x7eU, 0x02U, 0x79U, 0x08U, 0x03U, 0x65U, 0x6eU, 0x76U, 0x02U,
|
||||
0x5fU, 0x67U, 0x00U, 0x00U, 0x03U, 0x65U, 0x6eU, 0x76U, 0x0cU,
|
||||
0x68U, 0x6fU, 0x6fU, 0x6bU, 0x5fU, 0x61U, 0x63U, 0x63U, 0x6fU,
|
||||
0x75U, 0x6eU, 0x74U, 0x00U, 0x01U, 0x03U, 0x65U, 0x6eU, 0x76U,
|
||||
0x08U, 0x72U, 0x6fU, 0x6cU, 0x6cU, 0x62U, 0x61U, 0x63U, 0x6bU,
|
||||
0x00U, 0x02U, 0x03U, 0x65U, 0x6eU, 0x76U, 0x05U, 0x73U, 0x74U,
|
||||
0x61U, 0x74U, 0x65U, 0x00U, 0x03U, 0x03U, 0x65U, 0x6eU, 0x76U,
|
||||
0x05U, 0x74U, 0x72U, 0x61U, 0x63U, 0x65U, 0x00U, 0x04U, 0x03U,
|
||||
0x65U, 0x6eU, 0x76U, 0x11U, 0x73U, 0x74U, 0x61U, 0x74U, 0x65U,
|
||||
0x5fU, 0x66U, 0x6fU, 0x72U, 0x65U, 0x69U, 0x67U, 0x6eU, 0x5fU,
|
||||
0x73U, 0x65U, 0x74U, 0x00U, 0x05U, 0x03U, 0x65U, 0x6eU, 0x76U,
|
||||
0x09U, 0x73U, 0x74U, 0x61U, 0x74U, 0x65U, 0x5fU, 0x73U, 0x65U,
|
||||
0x74U, 0x00U, 0x03U, 0x03U, 0x65U, 0x6eU, 0x76U, 0x06U, 0x61U,
|
||||
0x63U, 0x63U, 0x65U, 0x70U, 0x74U, 0x00U, 0x02U, 0x03U, 0x02U,
|
||||
0x01U, 0x06U, 0x05U, 0x03U, 0x01U, 0x00U, 0x02U, 0x06U, 0x2bU,
|
||||
0x07U, 0x7fU, 0x01U, 0x41U, 0xc0U, 0x88U, 0x04U, 0x0bU, 0x7fU,
|
||||
0x00U, 0x41U, 0x80U, 0x08U, 0x0bU, 0x7fU, 0x00U, 0x41U, 0xb2U,
|
||||
0x08U, 0x0bU, 0x7fU, 0x00U, 0x41U, 0x80U, 0x08U, 0x0bU, 0x7fU,
|
||||
0x00U, 0x41U, 0xc0U, 0x88U, 0x04U, 0x0bU, 0x7fU, 0x00U, 0x41U,
|
||||
0x00U, 0x0bU, 0x7fU, 0x00U, 0x41U, 0x01U, 0x0bU, 0x07U, 0x08U,
|
||||
0x01U, 0x04U, 0x68U, 0x6fU, 0x6fU, 0x6bU, 0x00U, 0x08U, 0x0aU,
|
||||
0xd4U, 0x81U, 0x00U, 0x01U, 0xd0U, 0x81U, 0x00U, 0x02U, 0x02U,
|
||||
0x7fU, 0x01U, 0x7eU, 0x23U, 0x00U, 0x41U, 0xe0U, 0x00U, 0x6bU,
|
||||
0x22U, 0x01U, 0x24U, 0x00U, 0x20U, 0x01U, 0x20U, 0x00U, 0x36U,
|
||||
0x02U, 0x5cU, 0x41U, 0x01U, 0x41U, 0x01U, 0x10U, 0x00U, 0x1aU,
|
||||
0x20U, 0x01U, 0x41U, 0x40U, 0x6bU, 0x41U, 0x14U, 0x10U, 0x01U,
|
||||
0x42U, 0x14U, 0x52U, 0x04U, 0x40U, 0x41U, 0x00U, 0x41U, 0x00U,
|
||||
0x42U, 0x0cU, 0x10U, 0x02U, 0x1aU, 0x0bU, 0x20U, 0x01U, 0x41U,
|
||||
0x38U, 0x6aU, 0x41U, 0x08U, 0x20U, 0x01U, 0x41U, 0x40U, 0x6bU,
|
||||
0x22U, 0x00U, 0x41U, 0x14U, 0x10U, 0x03U, 0x1aU, 0x20U, 0x01U,
|
||||
0x20U, 0x01U, 0x29U, 0x03U, 0x38U, 0x42U, 0x01U, 0x7cU, 0x37U,
|
||||
0x03U, 0x38U, 0x20U, 0x01U, 0x41U, 0xabU, 0x01U, 0x3aU, 0x00U,
|
||||
0x19U, 0x20U, 0x01U, 0x20U, 0x01U, 0x29U, 0x03U, 0x38U, 0x3cU,
|
||||
0x00U, 0x1aU, 0x41U, 0x80U, 0x08U, 0x41U, 0x02U, 0x20U, 0x01U,
|
||||
0x41U, 0x10U, 0x6aU, 0x22U, 0x02U, 0x41U, 0x20U, 0x41U, 0x01U,
|
||||
0x10U, 0x04U, 0x1aU, 0x20U, 0x01U, 0x41U, 0xa9U, 0x08U, 0x41U,
|
||||
0x09U, 0x41U, 0xa4U, 0x08U, 0x41U, 0x05U, 0x20U, 0x02U, 0x41U,
|
||||
0x20U, 0x20U, 0x00U, 0x41U, 0x14U, 0x10U, 0x05U, 0x37U, 0x03U,
|
||||
0x08U, 0x20U, 0x01U, 0x29U, 0x03U, 0x08U, 0x42U, 0x00U, 0x53U,
|
||||
0x04U, 0x40U, 0x41U, 0x83U, 0x08U, 0x41U, 0x21U, 0x20U, 0x01U,
|
||||
0x29U, 0x03U, 0x08U, 0x10U, 0x02U, 0x1aU, 0x0bU, 0x20U, 0x01U,
|
||||
0x41U, 0x38U, 0x6aU, 0x41U, 0x08U, 0x20U, 0x01U, 0x41U, 0x40U,
|
||||
0x6bU, 0x41U, 0x14U, 0x10U, 0x06U, 0x1aU, 0x41U, 0x00U, 0x41U,
|
||||
0x00U, 0x20U, 0x01U, 0x29U, 0x03U, 0x08U, 0x10U, 0x07U, 0x20U,
|
||||
0x01U, 0x41U, 0xe0U, 0x00U, 0x6aU, 0x24U, 0x00U, 0x0bU, 0x0bU,
|
||||
0x38U, 0x01U, 0x00U, 0x41U, 0x80U, 0x08U, 0x0bU, 0x31U, 0x6eU,
|
||||
0x73U, 0x00U, 0x6eU, 0x73U, 0x5fU, 0x6dU, 0x61U, 0x78U, 0x2eU,
|
||||
0x63U, 0x3aU, 0x20U, 0x4dU, 0x61U, 0x78U, 0x20U, 0x4eU, 0x61U,
|
||||
0x6dU, 0x65U, 0x73U, 0x70U, 0x61U, 0x63U, 0x65U, 0x73U, 0x20U,
|
||||
0x52U, 0x65U, 0x61U, 0x63U, 0x68U, 0x65U, 0x64U, 0x00U, 0x6bU,
|
||||
0x65U, 0x79U, 0x32U, 0x00U, 0x63U, 0x6fU, 0x6eU, 0x74U, 0x65U,
|
||||
0x6eU, 0x74U, 0x32U};
|
||||
|
||||
// fixXahauV1
|
||||
{
|
||||
for (bool const withfixXahauV1 : {true, false})
|
||||
{
|
||||
auto const amend = withfixXahauV1
|
||||
? supported_amendments()
|
||||
: supported_amendments() - fixXahauV1;
|
||||
|
||||
Env env{*this, amend};
|
||||
|
||||
// Env env{*this, envconfig(), amend, nullptr,
|
||||
// // beast::severities::kWarning
|
||||
// beast::severities::kTrace
|
||||
// };
|
||||
|
||||
auto const bob = Account{"bob"};
|
||||
auto const alice = Account{"alice"};
|
||||
env.fund(XRP(10000000), alice);
|
||||
env.fund(XRP(10000000), bob);
|
||||
|
||||
// install the hook on alice
|
||||
env(ripple::test::jtx::hook(
|
||||
alice, {{hso(ns_maxHook, overrideFlag)}}, 0),
|
||||
M("set state_foreign_set_max"),
|
||||
HSFEE);
|
||||
env.close();
|
||||
|
||||
// invoke the hook
|
||||
for (uint32_t i = 0; i < 255; ++i)
|
||||
{
|
||||
env(pay(bob, alice, XRP(1)),
|
||||
M("test state_foreign_set_max"),
|
||||
fee(XRP(1)));
|
||||
}
|
||||
|
||||
auto const txResult =
|
||||
withfixXahauV1 ? ter(tecHOOK_REJECTED) : ter(tesSUCCESS);
|
||||
env(pay(bob, alice, XRP(1)),
|
||||
M("test state_foreign_set_max"),
|
||||
fee(XRP(1)),
|
||||
ter(txResult));
|
||||
env.close();
|
||||
|
||||
// verify hook result
|
||||
std::string const hookResult = withfixXahauV1
|
||||
? "800000000000002d" // TOO_MANY_NAMESPACES / -45
|
||||
: "9";
|
||||
|
||||
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[sfHookReturnCode.jsonName] == hookResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test_state_foreign_set()
|
||||
{
|
||||
@@ -11437,6 +11627,7 @@ public:
|
||||
void
|
||||
run() override
|
||||
{
|
||||
testHooksOwnerDir();
|
||||
testHooksDisabled();
|
||||
testTxStructure();
|
||||
testInferHookSetOperation();
|
||||
@@ -11520,10 +11711,11 @@ public:
|
||||
test_slot_subfield(); //
|
||||
test_slot_type(); //
|
||||
|
||||
test_state(); //
|
||||
test_state_foreign(); //
|
||||
test_state_foreign_set(); //
|
||||
test_state_set(); //
|
||||
test_state(); //
|
||||
test_state_foreign(); //
|
||||
test_state_foreign_set(); //
|
||||
test_state_foreign_set_max(); //
|
||||
test_state_set(); //
|
||||
|
||||
test_sto_emplace(); //
|
||||
test_sto_erase(); //
|
||||
|
||||
@@ -43,12 +43,18 @@ finish(
|
||||
jtx::Account const& from,
|
||||
std::uint32_t seq);
|
||||
|
||||
Json::Value
|
||||
finish(jtx::Account const& account, jtx::Account const& from);
|
||||
|
||||
Json::Value
|
||||
cancel(
|
||||
jtx::Account const& account,
|
||||
jtx::Account const& from,
|
||||
std::uint32_t seq);
|
||||
|
||||
Json::Value
|
||||
cancel(jtx::Account const& account, jtx::Account const& from);
|
||||
|
||||
/** Set the "FinishAfter" time tag on a JTx */
|
||||
class finish_time
|
||||
{
|
||||
|
||||
@@ -84,6 +84,17 @@ finish(jtx::Account const& account, jtx::Account const& from, std::uint32_t seq)
|
||||
return jv;
|
||||
}
|
||||
|
||||
Json::Value
|
||||
finish(jtx::Account const& account, jtx::Account const& from)
|
||||
{
|
||||
Json::Value jv;
|
||||
jv[jss::TransactionType] = jss::EscrowFinish;
|
||||
jv[jss::Flags] = tfUniversal;
|
||||
jv[jss::Account] = account.human();
|
||||
jv[sfOwner.jsonName] = from.human();
|
||||
return jv;
|
||||
}
|
||||
|
||||
Json::Value
|
||||
cancel(jtx::Account const& account, jtx::Account const& from, std::uint32_t seq)
|
||||
{
|
||||
@@ -96,6 +107,17 @@ cancel(jtx::Account const& account, jtx::Account const& from, std::uint32_t seq)
|
||||
return jv;
|
||||
}
|
||||
|
||||
Json::Value
|
||||
cancel(jtx::Account const& account, jtx::Account const& from)
|
||||
{
|
||||
Json::Value jv;
|
||||
jv[jss::TransactionType] = jss::EscrowCancel;
|
||||
jv[jss::Flags] = tfUniversal;
|
||||
jv[jss::Account] = account.human();
|
||||
jv[sfOwner.jsonName] = from.human();
|
||||
return jv;
|
||||
}
|
||||
|
||||
} // namespace escrow
|
||||
|
||||
} // namespace jtx
|
||||
|
||||
@@ -51,6 +51,15 @@ offer_cancel(Account const& account, std::uint32_t offerSeq)
|
||||
return jv;
|
||||
}
|
||||
|
||||
Json::Value
|
||||
offer_cancel(Account const& account)
|
||||
{
|
||||
Json::Value jv;
|
||||
jv[jss::Account] = account.human();
|
||||
jv[jss::TransactionType] = jss::OfferCancel;
|
||||
return jv;
|
||||
}
|
||||
|
||||
void
|
||||
offer_id::operator()(Env& env, JTx& jt) const
|
||||
{
|
||||
|
||||
@@ -40,6 +40,10 @@ offer(
|
||||
Json::Value
|
||||
offer_cancel(Account const& account, std::uint32_t offerSeq);
|
||||
|
||||
/** Cancel an offer. */
|
||||
Json::Value
|
||||
offer_cancel(Account const& account);
|
||||
|
||||
/** Sets the optional "OfferID" on a JTx. */
|
||||
class offer_id
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user