Compare commits

..

8 Commits

Author SHA1 Message Date
Richard Holland
b2b4ff8e4d Remit squashed
Co-authored-by: Denis Angell <dangell@transia.co>
2024-01-22 09:51:48 +00:00
Denis Angell
f5981a23f7 add ttREMIT to tsh 2024-01-22 09:51:48 +00:00
Denis Angell
5a6391a1fb Update tts.h 2024-01-22 09:51:48 +00:00
Denis Angell
78f0cc2768 add test: preflight / doapply 2024-01-22 09:51:48 +00:00
Denis Angell
1d915501b7 add: remit.h 2024-01-22 09:51:47 +00:00
Denis Angell
f6cd727b76 nit: log 2024-01-22 09:51:47 +00:00
Richard Holland
0bf66db094 change remit to use accountsend (more changes needed) 2024-01-22 09:51:47 +00:00
Richard Holland
b1e3e746ca Remit squashed (not compiling)
Co-authored-by: Denis Angell <dangell@transia.co>
2024-01-22 09:51:46 +00:00
17 changed files with 402 additions and 2985 deletions

View File

@@ -12,13 +12,10 @@ if [[ "$GITHUB_REPOSITORY" == "" ]]; then
BUILD_CORES=8
fi
CONTAINER_NAME=xahaud_cached_builder_$(echo "$GITHUB_ACTOR" | awk '{print tolower($0)}')
echo "-- BUILD CORES: $BUILD_CORES"
echo "-- GITHUB_REPOSITORY: $GITHUB_REPOSITORY"
echo "-- GITHUB_SHA: $GITHUB_SHA"
echo "-- GITHUB_RUN_NUMBER: $GITHUB_RUN_NUMBER"
echo "-- CONTAINER_NAME: $CONTAINER_NAME"
which docker 2> /dev/null 2> /dev/null
if [ "$?" -eq "1" ]
@@ -34,13 +31,13 @@ then
exit 1
fi
STATIC_CONTAINER=$(docker ps -a | grep $CONTAINER_NAME |wc -l)
STATIC_CONTAINER=$(docker ps -a | grep xahaud_cached_builder |wc -l)
if [[ "$STATIC_CONTAINER" -gt "0" && "$GITHUB_REPOSITORY" != "" ]]; then
echo "Static container, execute in static container to have max. cache"
docker start $CONTAINER_NAME
docker exec -i $CONTAINER_NAME /hbb_exe/activate-exec bash -x /io/build-core.sh "$GITHUB_REPOSITORY" "$GITHUB_SHA" "$BUILD_CORES" "$GITHUB_RUN_NUMBER"
docker stop $CONTAINER_NAME
docker start xahaud_cached_builder
docker exec -i xahaud_cached_builder /hbb_exe/activate-exec bash -x /io/build-core.sh "$GITHUB_REPOSITORY" "$GITHUB_SHA" "$BUILD_CORES" "$GITHUB_RUN_NUMBER"
docker stop xahaud_cached_builder
else
echo "No static container, build on temp container"
rm -rf release-build;
@@ -53,10 +50,10 @@ else
else
# GH Action, runner
echo "GH Action, runner, clean & re-create create persistent container"
docker rm -f $CONTAINER_NAME
docker run -di --user 0:$(id -g) --name $CONTAINER_NAME -v /data/builds:/data/builds -v `pwd`:/io --network host ghcr.io/foobarwidget/holy-build-box-x64 /hbb_exe/activate-exec bash
docker exec -i $CONTAINER_NAME /hbb_exe/activate-exec bash -x /io/build-full.sh "$GITHUB_REPOSITORY" "$GITHUB_SHA" "$BUILD_CORES" "$GITHUB_RUN_NUMBER"
docker stop $CONTAINER_NAME
docker rm -f xahaud_cached_builder
docker run -di --user 0:$(id -g) --name xahaud_cached_builder -v /data/builds:/data/builds -v `pwd`:/io --network host ghcr.io/foobarwidget/holy-build-box-x64 /hbb_exe/activate-exec bash
docker exec -i xahaud_cached_builder /hbb_exe/activate-exec bash -x /io/build-full.sh "$GITHUB_REPOSITORY" "$GITHUB_SHA" "$BUILD_CORES" "$GITHUB_RUN_NUMBER"
docker stop xahaud_cached_builder
fi
fi

View File

@@ -70,45 +70,6 @@ getTransactionalStakeHolders(STTx const& tx, ReadView const& rv)
switch (tt)
{
case ttREMIT: {
if (destAcc)
ADD_TSH(*destAcc, tshSTRONG);
if (tx.isFieldPresent(sfInform))
{
auto const inform = tx.getAccountID(sfInform);
if (*otxnAcc != inform && *destAcc != inform)
ADD_TSH(inform, tshWEAK);
}
if (tx.isFieldPresent(sfURITokenIDs))
{
STVector256 tokenIds = tx.getFieldV256(sfURITokenIDs);
for (uint256 const klRaw : tokenIds)
{
Keylet const id{ltURI_TOKEN, klRaw};
if (!rv.exists(id))
continue;
auto const ut = rv.read(id);
if (!ut ||
ut->getFieldU16(sfLedgerEntryType) != ltURI_TOKEN)
continue;
auto const owner = ut->getAccountID(sfOwner);
auto const issuer = ut->getAccountID(sfIssuer);
if (issuer != owner && issuer != *destAcc)
{
ADD_TSH(
issuer,
(ut->getFlags() & lsfBurnable) ? tshSTRONG
: tshWEAK);
}
}
}
break;
}
case ttIMPORT: {
if (tx.isFieldPresent(sfIssuer))
ADD_TSH(tx.getAccountID(sfIssuer), fixV2 ? tshWEAK : tshSTRONG);
@@ -295,14 +256,14 @@ getTransactionalStakeHolders(STTx const& tx, ReadView const& rv)
{
ADD_TSH(bo->getAccountID(sfOwner), tshSTRONG);
if (bo->isFieldPresent(sfDestination))
ADD_TSH(bo->getAccountID(sfDestination), tshSTRONG);
ADD_TSH(bo->getAccountID(sfDestination), tshWEAK);
}
if (so)
{
ADD_TSH(so->getAccountID(sfOwner), tshSTRONG);
if (so->isFieldPresent(sfDestination))
ADD_TSH(so->getAccountID(sfDestination), tshSTRONG);
ADD_TSH(so->getAccountID(sfDestination), tshWEAK);
}
break;
@@ -318,7 +279,7 @@ getTransactionalStakeHolders(STTx const& tx, ReadView const& rv)
auto const offer = getNFTOffer(offerID, rv);
if (offer)
{
ADD_TSH(offer->getAccountID(sfOwner), tshWEAK);
ADD_TSH(offer->getAccountID(sfOwner), tshSTRONG);
if (offer->isFieldPresent(sfDestination))
ADD_TSH(offer->getAccountID(sfDestination), tshWEAK);
@@ -357,6 +318,7 @@ getTransactionalStakeHolders(STTx const& tx, ReadView const& rv)
}
// simple two party transactions
case ttREMIT:
case ttPAYMENT:
case ttESCROW_CREATE:
case ttCHECK_CREATE:
@@ -1896,8 +1858,7 @@ hook::finalizeHookResult(
uint16_t exec_index = avi.nextHookExecutionIndex();
// apply emitted transactions to the ledger (by adding them to the emitted
// directory) if we are allowed to
std::vector<std::pair<uint256 /* txnid */, uint256 /* emit nonce */>>
emission_txnid;
std::map<uint256 /* txnid */, uint256 /* emit nonce */> emission_txnid;
if (doEmit)
{
@@ -1922,7 +1883,7 @@ hook::finalizeHookResult(
.getField(sfEmitDetails)
.downcast<STObject>();
emission_txnid.emplace_back(
emission_txnid.emplace(
id, emitDetails.getFieldH256(sfEmitNonce));
sleEmitted = std::make_shared<SLE>(emittedId);

View File

@@ -386,17 +386,6 @@ LedgerHistory::handleMismatch(
JLOG(j_.error()) << "built\n" << getJson({*builtLedger, {}});
JLOG(j_.error()) << "valid\n" << getJson({*validLedger, {}});
{
auto b = builtTx.begin();
auto v = validTx.begin();
while (b != builtTx.end() && v != validTx.end())
{
log_one(*builtLedger, (*b)->key(), "validInfo", j_);
log_one(*validLedger, (*v)->key(), "builtInfo", j_);
++b;
++v;
}
}
// Log all differences between built and valid ledgers
auto b = builtTx.begin();
auto v = validTx.begin();

View File

@@ -28,23 +28,7 @@ namespace ripple {
TxConsequences
Remit::makeTxConsequences(PreflightContext const& ctx)
{
XRPAmount native = ([&ctx]() -> XRPAmount {
if (!ctx.tx.isFieldPresent(sfAmounts))
return beast::zero;
STArray const& sEntries(ctx.tx.getFieldArray(sfAmounts));
for (STObject const& sEntry : sEntries)
{
if (!sEntry.isFieldPresent(sfAmount))
continue;
STAmount const amount = sEntry.getFieldAmount(sfAmount);
if (isXRP(amount))
return amount.xrp();
}
return beast::zero;
})();
return TxConsequences{ctx.tx, native};
return TxConsequences{ctx.tx, TxConsequences::normal};
}
NotTEC
@@ -69,34 +53,9 @@ Remit::preflight(PreflightContext const& ctx)
return temREDUNDANT;
}
if (ctx.tx.isFieldPresent(sfInform))
{
AccountID const infID = ctx.tx.getAccountID(sfInform);
if (infID == dstID || srcID == infID)
{
JLOG(ctx.j.warn()) << "Malformed transaction: sfInform is same as "
"source or destination.";
return temMALFORMED;
}
}
if (ctx.tx.isFieldPresent(sfBlob) &&
ctx.tx.getFieldVL(sfBlob).size() > (128 * 1024))
{
JLOG(ctx.j.warn()) << "Blob was more than 128kib "
<< ctx.tx.getTransactionID();
return temMALFORMED;
}
// sanity check amounts
if (ctx.tx.isFieldPresent(sfAmounts))
{
if (ctx.tx.getFieldArray(sfAmounts).size() > 32)
{
JLOG(ctx.j.warn()) << "Malformed: AmountEntry count exceeds `32`.";
return temMALFORMED;
}
std::map<Currency, std::set<AccountID>> already;
bool nativeAlready = false;
@@ -113,7 +72,7 @@ Remit::preflight(PreflightContext const& ctx)
STAmount const amount = sEntry.getFieldAmount(sfAmount);
if (!isLegalNet(amount) || amount.signum() <= 0)
{
JLOG(ctx.j.warn()) << "Malformed transaction: bad amount: "
JLOG(ctx.j.warn()) << "Malformed transaction: Bad amount: "
<< amount.getFullText();
return temBAD_AMOUNT;
}
@@ -163,23 +122,8 @@ Remit::preflight(PreflightContext const& ctx)
STObject const& mint = const_cast<ripple::STTx&>(ctx.tx)
.getField(sfMintURIToken)
.downcast<STObject>();
// RH TODO: iterate mint fields detect any that shouldnt be there
for (auto const& mintElement : mint)
{
auto const& name = mintElement.getFName();
if (name != sfURI && name != sfFlags && name != sfDigest)
{
JLOG(ctx.j.trace()) << "Malformed transaction: sfMintURIToken "
"contains invalid field.";
return temMALFORMED;
}
}
if (!mint.isFieldPresent(sfURI))
{
JLOG(ctx.j.warn())
<< "Malformed transaction: URI was not provided.";
return temMALFORMED;
}
Blob const uri = mint.getFieldVL(sfURI);
if (uri.size() < 1 || uri.size() > 256)
{
@@ -188,7 +132,7 @@ Remit::preflight(PreflightContext const& ctx)
return temMALFORMED;
}
if (!URIToken::validateUTF8(uri))
if (!URIToken::validateUTF8(mint.getFieldVL(sfURI)))
{
JLOG(ctx.j.warn())
<< "Malformed transaction: Invalid UTF8 inside MintURIToken.";
@@ -202,16 +146,10 @@ Remit::preflight(PreflightContext const& ctx)
}
}
// sanity check uritokenids
// check uritokenids for duplicates
if (ctx.tx.isFieldPresent(sfURITokenIDs))
{
STVector256 ids = ctx.tx.getFieldV256(sfURITokenIDs);
if (ids.size() < 1 || ids.size() > 32)
{
JLOG(ctx.j.warn()) << "Malformed transaction: URITokenIDs Invalid.";
return temMALFORMED;
}
std::sort(ids.begin(), ids.end());
if (std::adjacent_find(ids.begin(), ids.end()) != ids.end())
{
@@ -227,11 +165,11 @@ Remit::preflight(PreflightContext const& ctx)
TER
Remit::doApply()
{
Sandbox sb(&ctx_.view());
if (!sb.rules().enabled(featureRemit))
if (!view().rules().enabled(featureRemit))
return temDISABLED;
Sandbox sb(&ctx_.view());
beast::Journal const& j = ctx_.journal;
auto const srcAccID = ctx_.tx[sfAccount];
@@ -240,28 +178,9 @@ Remit::doApply()
if (!sleSrcAcc)
return terNO_ACCOUNT;
if (ctx_.tx.isFieldPresent(sfInform))
{
auto const informAcc = ctx_.tx.getAccountID(sfInform);
if (!sb.exists(keylet::account(informAcc)))
{
JLOG(j.warn()) << "Remit: sfInform account does not exist.";
return tecNO_TARGET;
}
}
XRPAmount const accountReserve{sb.fees().accountReserve(0)};
XRPAmount const objectReserve{sb.fees().accountReserve(1) - accountReserve};
// sanity check
if (accountReserve < beast::zero || objectReserve < beast::zero ||
objectReserve > sb.fees().accountReserve(1))
{
JLOG(j.warn())
<< "Remit: account or object reserve calculation not sane.";
return tecINTERNAL;
}
// amount of native tokens we will transfer to cover reserves for the
// tls/acc/uritokens created, and native tokens listed in amounts
XRPAmount nativeRemit{0};
@@ -275,14 +194,6 @@ Remit::doApply()
(flags & lsfDisallowIncomingRemit))
return tecNO_PERMISSION;
// Check if the destination account requires deposit authorization.
bool const depositAuth{sb.rules().enabled(featureDepositAuth)};
if (depositAuth && sleDstAcc && (flags & lsfDepositAuth))
{
if (!sb.exists(keylet::depositPreauth(dstAccID, srcAccID)))
return tecNO_PERMISSION;
}
// the destination may require a dest tag
if ((flags & lsfRequireDestTag) &&
!ctx_.tx.isFieldPresent(sfDestinationTag))
@@ -297,9 +208,6 @@ Remit::doApply()
if (createDst)
{
// sender will pay the reserve
if (nativeRemit + accountReserve < nativeRemit)
return tecINTERNAL;
nativeRemit += accountReserve;
// Create the account.
@@ -334,9 +242,6 @@ Remit::doApply()
// if theres a minted uritoken the sender pays for that
if (ctx_.tx.isFieldPresent(sfMintURIToken))
{
if (nativeRemit + objectReserve < nativeRemit)
return tecINTERNAL;
nativeRemit += objectReserve;
STObject const& mint = const_cast<ripple::STTx&>(ctx_.tx)
.getField(sfMintURIToken)
@@ -372,7 +277,7 @@ Remit::doApply()
sfFlags,
mint.isFieldPresent(sfFlags) ? mint.getFieldU32(sfFlags) : 0);
auto const page = sb.dirInsert(
auto const page = view().dirInsert(
keylet::ownerDir(dstAccID), kl, describeOwnerDir(dstAccID));
JLOG(j_.trace()) << "Adding URIToken to owner directory "
@@ -406,7 +311,7 @@ Remit::doApply()
{
JLOG(j.warn()) << "Remit: one or more uritokens did not exist "
"on the source account.";
return tecNO_ENTRY;
return tecUNFUNDED_PAYMENT;
}
// is it a uritoken?
@@ -432,9 +337,6 @@ Remit::doApply()
sleU->makeFieldAbsent(sfDestination);
// pay the reserve
if (nativeRemit + objectReserve < nativeRemit)
return tecINTERNAL;
nativeRemit += objectReserve;
// remove from sender dir
@@ -488,11 +390,6 @@ Remit::doApply()
// since we have to pay for all the created objects including
// possibly the account itself this is paid right at the end,
// and only if there is balance enough to cover.
// check for overflow
if (nativeRemit + amount.xrp() < nativeRemit)
return tecINTERNAL;
nativeRemit += amount.xrp();
continue;
}
@@ -523,13 +420,6 @@ Remit::doApply()
? multiply(amount, transferRate(sb, issuerAccID))
: amount;
// sanity check this calculation
if (srcAmt < amount || srcAmt > amount + amount)
{
JLOG(j.warn()) << "Remit: srcAmt calculation not sane.";
return tecINTERNAL;
}
STAmount availableFunds{
accountFunds(sb, srcAccID, srcAmt, fhZERO_IF_FROZEN, j)};
@@ -538,18 +428,15 @@ Remit::doApply()
// if the target trustline doesn't exist we need to create it and
// pay its reserve
if (!sb.exists(
keylet::line(dstAccID, issuerAccID, amount.getCurrency())))
{
if (nativeRemit + objectReserve < nativeRemit)
return tecINTERNAL;
if (!sb.exists(keylet::line(
issuerAccID == dstAccID ? srcAccID : dstAccID,
issuerAccID,
amount.getCurrency())))
nativeRemit += objectReserve;
}
// action the transfer
if (TER result =
accountSend(sb, srcAccID, dstAccID, amount, j, true);
accountSend(sb, srcAccID, dstAccID, amount, j, false);
result != tesSUCCESS)
return result;
}
@@ -623,6 +510,8 @@ Remit::calculateBaseFee(ReadView const& view, STTx const& tx)
extraFee +=
XRPAmount{static_cast<XRPAmount>(tx.getFieldVL(sfBlob).size())};
// RH TODO: add fees
return Transactor::calculateBaseFee(view, tx) + extraFee;
}

View File

@@ -148,6 +148,7 @@ InnerObjectFormats::InnerObjectFormats()
sfAmountEntry.getCode(),
{
{sfAmount, soeREQUIRED},
{sfFlags, soeOPTIONAL},
});
add(sfMintURIToken.jsonName.c_str(),

View File

@@ -131,38 +131,6 @@ TxMeta::getAffectedAccounts() const
// This code should match the behavior of the JS method:
// Meta#getAffectedAccounts
// Add HookExecution HookAccount/s to stream
for (auto const& ex : *mHookExecutions)
{
const STObject* inner = dynamic_cast<const STObject*>(&ex);
for (auto const& field : *inner)
{
if (auto sa = dynamic_cast<STAccount const*>(&field))
{
assert(!sa->isDefault());
if (!sa->isDefault())
list.insert(sa->value());
}
}
}
// Add HookEmission HookAccount/s to stream
for (auto const& em : *mHookEmissions)
{
const STObject* inner = dynamic_cast<const STObject*>(&em);
for (auto const& field : *inner)
{
if (auto sa = dynamic_cast<STAccount const*>(&field))
{
assert(!sa->isDefault());
if (!sa->isDefault())
list.insert(sa->value());
}
}
}
// Add AffectedNodes Account/s to stream
for (auto const& it : mNodes)
{
int index = it.getFieldIndex(

View File

@@ -91,14 +91,13 @@ doAccountInfo(RPC::JsonContext& context)
{"requireDestinationTag", lsfRequireDestTag}}};
static constexpr std::
array<std::pair<std::string_view, LedgerSpecificFlags>, 5>
array<std::pair<std::string_view, LedgerSpecificFlags>, 4>
disallowIncomingFlags{
{{"disallowIncomingNFTokenOffer",
lsfDisallowIncomingNFTokenOffer},
{"disallowIncomingCheck", lsfDisallowIncomingCheck},
{"disallowIncomingPayChan", lsfDisallowIncomingPayChan},
{"disallowIncomingTrustline", lsfDisallowIncomingTrustline},
{"disallowIncomingRemit", lsfDisallowIncomingRemit}}};
{"disallowIncomingTrustline", lsfDisallowIncomingTrustline}}};
auto const sleAccepted = ledger->read(keylet::account(accountID));
if (sleAccepted)

File diff suppressed because it is too large Load Diff

View File

@@ -292,215 +292,6 @@ private:
0x00U, 0x73U, 0x21U, 0x00U, 0x41U, 0x9BU, 0x0AU, 0x0BU, 0x02U, 0x81U,
0x14U, 0x00U, 0x41U, 0xB1U, 0x0AU, 0x0BU, 0x02U, 0x83U, 0x14U};
const std::vector<uint8_t> EmitTenHook = {
0x00U, 0x61U, 0x73U, 0x6DU, 0x01U, 0x00U, 0x00U, 0x00U, 0x01U, 0x35U,
0x08U, 0x60U, 0x05U, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x01U, 0x7EU,
0x60U, 0x02U, 0x7FU, 0x7FU, 0x01U, 0x7EU, 0x60U, 0x01U, 0x7FU, 0x01U,
0x7EU, 0x60U, 0x02U, 0x7FU, 0x7FU, 0x01U, 0x7FU, 0x60U, 0x03U, 0x7FU,
0x7FU, 0x7EU, 0x01U, 0x7EU, 0x60U, 0x04U, 0x7FU, 0x7FU, 0x7FU, 0x7FU,
0x01U, 0x7EU, 0x60U, 0x00U, 0x01U, 0x7EU, 0x60U, 0x03U, 0x7FU, 0x7FU,
0x7FU, 0x01U, 0x7EU, 0x02U, 0xBEU, 0x01U, 0x0CU, 0x03U, 0x65U, 0x6EU,
0x76U, 0x05U, 0x74U, 0x72U, 0x61U, 0x63U, 0x65U, 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, 0x0CU, 0x65U, 0x74U, 0x78U, 0x6EU, 0x5FU, 0x72U, 0x65U,
0x73U, 0x65U, 0x72U, 0x76U, 0x65U, 0x00U, 0x02U, 0x03U, 0x65U, 0x6EU,
0x76U, 0x02U, 0x5FU, 0x67U, 0x00U, 0x03U, 0x03U, 0x65U, 0x6EU, 0x76U,
0x09U, 0x74U, 0x72U, 0x61U, 0x63U, 0x65U, 0x5FU, 0x6EU, 0x75U, 0x6DU,
0x00U, 0x04U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x0AU, 0x75U, 0x74U, 0x69U,
0x6CU, 0x5FU, 0x61U, 0x63U, 0x63U, 0x69U, 0x64U, 0x00U, 0x05U, 0x03U,
0x65U, 0x6EU, 0x76U, 0x0AU, 0x6CU, 0x65U, 0x64U, 0x67U, 0x65U, 0x72U,
0x5FU, 0x73U, 0x65U, 0x71U, 0x00U, 0x06U, 0x03U, 0x65U, 0x6EU, 0x76U,
0x0AU, 0x6FU, 0x74U, 0x78U, 0x6EU, 0x5FU, 0x66U, 0x69U, 0x65U, 0x6CU,
0x64U, 0x00U, 0x07U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x0CU, 0x65U, 0x74U,
0x78U, 0x6EU, 0x5FU, 0x64U, 0x65U, 0x74U, 0x61U, 0x69U, 0x6CU, 0x73U,
0x00U, 0x01U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x0DU, 0x65U, 0x74U, 0x78U,
0x6EU, 0x5FU, 0x66U, 0x65U, 0x65U, 0x5FU, 0x62U, 0x61U, 0x73U, 0x65U,
0x00U, 0x01U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x04U, 0x65U, 0x6DU, 0x69U,
0x74U, 0x00U, 0x05U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x06U, 0x61U, 0x63U,
0x63U, 0x65U, 0x70U, 0x74U, 0x00U, 0x04U, 0x03U, 0x02U, 0x01U, 0x02U,
0x05U, 0x03U, 0x01U, 0x00U, 0x02U, 0x06U, 0x31U, 0x08U, 0x7FU, 0x01U,
0x41U, 0xD0U, 0x8DU, 0x04U, 0x0BU, 0x7FU, 0x00U, 0x41U, 0xB0U, 0x0BU,
0x0BU, 0x7FU, 0x00U, 0x41U, 0x80U, 0x08U, 0x0BU, 0x7FU, 0x00U, 0x41U,
0xCBU, 0x0DU, 0x0BU, 0x7FU, 0x00U, 0x41U, 0x80U, 0x08U, 0x0BU, 0x7FU,
0x00U, 0x41U, 0xD0U, 0x8DU, 0x04U, 0x0BU, 0x7FU, 0x00U, 0x41U, 0x00U,
0x0BU, 0x7FU, 0x00U, 0x41U, 0x01U, 0x0BU, 0x07U, 0x08U, 0x01U, 0x04U,
0x68U, 0x6FU, 0x6FU, 0x6BU, 0x00U, 0x0CU, 0x0AU, 0x9AU, 0x89U, 0x00U,
0x01U, 0x96U, 0x89U, 0x00U, 0x02U, 0x02U, 0x7FU, 0x01U, 0x7EU, 0x23U,
0x00U, 0x41U, 0x80U, 0x01U, 0x6BU, 0x22U, 0x01U, 0x24U, 0x00U, 0x20U,
0x01U, 0x20U, 0x00U, 0x36U, 0x02U, 0x7CU, 0x41U, 0x9AU, 0x0BU, 0x41U,
0x14U, 0x41U, 0x87U, 0x0BU, 0x41U, 0x13U, 0x41U, 0x00U, 0x10U, 0x00U,
0x1AU, 0x41U, 0xADU, 0x0CU, 0x41U, 0x14U, 0x10U, 0x01U, 0x1AU, 0x41U,
0x0AU, 0x10U, 0x02U, 0x1AU, 0x20U, 0x01U, 0x42U, 0x00U, 0x37U, 0x03U,
0x58U, 0x03U, 0x40U, 0x41U, 0xB9U, 0x80U, 0x80U, 0x80U, 0x78U, 0x41U,
0x0BU, 0x10U, 0x03U, 0x1AU, 0x02U, 0x40U, 0x20U, 0x01U, 0x29U, 0x03U,
0x58U, 0x42U, 0x09U, 0x55U, 0x0DU, 0x00U, 0x41U, 0xD6U, 0x08U, 0x41U,
0x01U, 0x20U, 0x01U, 0x29U, 0x03U, 0x58U, 0x10U, 0x04U, 0x1AU, 0x20U,
0x01U, 0x29U, 0x03U, 0x58U, 0x22U, 0x03U, 0xA7U, 0x21U, 0x00U, 0x20U,
0x03U, 0x42U, 0x09U, 0x58U, 0x04U, 0x40U, 0x02U, 0x40U, 0x02U, 0x40U,
0x02U, 0x40U, 0x02U, 0x40U, 0x02U, 0x40U, 0x02U, 0x40U, 0x02U, 0x40U,
0x02U, 0x40U, 0x02U, 0x40U, 0x02U, 0x40U, 0x20U, 0x00U, 0x41U, 0x01U,
0x6BU, 0x0EU, 0x09U, 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U,
0x08U, 0x09U, 0x00U, 0x0BU, 0x41U, 0xC3U, 0x0CU, 0x41U, 0x14U, 0x41U,
0xB3U, 0x08U, 0x41U, 0x23U, 0x10U, 0x05U, 0x1AU, 0x0BU, 0x41U, 0xC3U,
0x0CU, 0x41U, 0x14U, 0x41U, 0xE4U, 0x09U, 0x41U, 0x23U, 0x10U, 0x05U,
0x1AU, 0x0BU, 0x41U, 0xC3U, 0x0CU, 0x41U, 0x14U, 0x41U, 0xFBU, 0x08U,
0x41U, 0x23U, 0x10U, 0x05U, 0x1AU, 0x0BU, 0x41U, 0xC3U, 0x0CU, 0x41U,
0x14U, 0x41U, 0xCDU, 0x0AU, 0x41U, 0x23U, 0x10U, 0x05U, 0x1AU, 0x0BU,
0x41U, 0xC3U, 0x0CU, 0x41U, 0x14U, 0x41U, 0xD8U, 0x08U, 0x41U, 0x23U,
0x10U, 0x05U, 0x1AU, 0x0BU, 0x41U, 0xC3U, 0x0CU, 0x41U, 0x14U, 0x41U,
0xAAU, 0x0AU, 0x41U, 0x23U, 0x10U, 0x05U, 0x1AU, 0x0BU, 0x41U, 0xC3U,
0x0CU, 0x41U, 0x14U, 0x41U, 0x8CU, 0x08U, 0x41U, 0x23U, 0x10U, 0x05U,
0x1AU, 0x0BU, 0x41U, 0xC3U, 0x0CU, 0x41U, 0x14U, 0x41U, 0xC1U, 0x09U,
0x41U, 0x23U, 0x10U, 0x05U, 0x1AU, 0x0BU, 0x41U, 0xC3U, 0x0CU, 0x41U,
0x14U, 0x41U, 0x9EU, 0x09U, 0x41U, 0x23U, 0x10U, 0x05U, 0x1AU, 0x0BU,
0x41U, 0xC3U, 0x0CU, 0x41U, 0x14U, 0x41U, 0x87U, 0x0AU, 0x41U, 0x23U,
0x10U, 0x05U, 0x1AU, 0x0BU, 0x20U, 0x01U, 0x10U, 0x06U, 0xA7U, 0x41U,
0x01U, 0x6AU, 0x36U, 0x02U, 0x54U, 0x41U, 0xC4U, 0x0BU, 0x20U, 0x01U,
0x28U, 0x02U, 0x54U, 0x22U, 0x00U, 0x41U, 0xFFU, 0x01U, 0x71U, 0x41U,
0x18U, 0x74U, 0x20U, 0x00U, 0x41U, 0x80U, 0xFEU, 0x03U, 0x71U, 0x41U,
0x08U, 0x74U, 0x72U, 0x20U, 0x00U, 0x41U, 0x80U, 0x80U, 0xFCU, 0x07U,
0x71U, 0x41U, 0x08U, 0x76U, 0x72U, 0x20U, 0x00U, 0x41U, 0x80U, 0x80U,
0x80U, 0x78U, 0x71U, 0x41U, 0x18U, 0x76U, 0x72U, 0x36U, 0x02U, 0x00U,
0x20U, 0x01U, 0x20U, 0x01U, 0x28U, 0x02U, 0x54U, 0x41U, 0x04U, 0x6AU,
0x36U, 0x02U, 0x50U, 0x41U, 0xCAU, 0x0BU, 0x20U, 0x01U, 0x28U, 0x02U,
0x50U, 0x22U, 0x00U, 0x41U, 0xFFU, 0x01U, 0x71U, 0x41U, 0x18U, 0x74U,
0x20U, 0x00U, 0x41U, 0x80U, 0xFEU, 0x03U, 0x71U, 0x41U, 0x08U, 0x74U,
0x72U, 0x20U, 0x00U, 0x41U, 0x80U, 0x80U, 0xFCU, 0x07U, 0x71U, 0x41U,
0x08U, 0x76U, 0x72U, 0x20U, 0x00U, 0x41U, 0x80U, 0x80U, 0x80U, 0x78U,
0x71U, 0x41U, 0x18U, 0x76U, 0x72U, 0x36U, 0x02U, 0x00U, 0x20U, 0x01U,
0x42U, 0xC0U, 0x84U, 0x3DU, 0x37U, 0x03U, 0x48U, 0x20U, 0x01U, 0x41U,
0xCFU, 0x0BU, 0x36U, 0x02U, 0x44U, 0x20U, 0x01U, 0x29U, 0x03U, 0x48U,
0x42U, 0x38U, 0x88U, 0x42U, 0x3FU, 0x83U, 0x42U, 0x40U, 0x7DU, 0xA7U,
0x21U, 0x00U, 0x20U, 0x01U, 0x20U, 0x01U, 0x28U, 0x02U, 0x44U, 0x22U,
0x02U, 0x41U, 0x01U, 0x6AU, 0x36U, 0x02U, 0x44U, 0x20U, 0x02U, 0x20U,
0x00U, 0x3AU, 0x00U, 0x00U, 0x20U, 0x01U, 0x29U, 0x03U, 0x48U, 0x42U,
0x30U, 0x88U, 0x42U, 0xFFU, 0x01U, 0x83U, 0xA7U, 0x21U, 0x00U, 0x20U,
0x01U, 0x20U, 0x01U, 0x28U, 0x02U, 0x44U, 0x22U, 0x02U, 0x41U, 0x01U,
0x6AU, 0x36U, 0x02U, 0x44U, 0x20U, 0x02U, 0x20U, 0x00U, 0x3AU, 0x00U,
0x00U, 0x20U, 0x01U, 0x29U, 0x03U, 0x48U, 0x42U, 0x28U, 0x88U, 0x42U,
0xFFU, 0x01U, 0x83U, 0xA7U, 0x21U, 0x00U, 0x20U, 0x01U, 0x20U, 0x01U,
0x28U, 0x02U, 0x44U, 0x22U, 0x02U, 0x41U, 0x01U, 0x6AU, 0x36U, 0x02U,
0x44U, 0x20U, 0x02U, 0x20U, 0x00U, 0x3AU, 0x00U, 0x00U, 0x20U, 0x01U,
0x29U, 0x03U, 0x48U, 0x42U, 0x20U, 0x88U, 0x42U, 0xFFU, 0x01U, 0x83U,
0xA7U, 0x21U, 0x00U, 0x20U, 0x01U, 0x20U, 0x01U, 0x28U, 0x02U, 0x44U,
0x22U, 0x02U, 0x41U, 0x01U, 0x6AU, 0x36U, 0x02U, 0x44U, 0x20U, 0x02U,
0x20U, 0x00U, 0x3AU, 0x00U, 0x00U, 0x20U, 0x01U, 0x29U, 0x03U, 0x48U,
0x42U, 0x18U, 0x88U, 0x42U, 0xFFU, 0x01U, 0x83U, 0xA7U, 0x21U, 0x00U,
0x20U, 0x01U, 0x20U, 0x01U, 0x28U, 0x02U, 0x44U, 0x22U, 0x02U, 0x41U,
0x01U, 0x6AU, 0x36U, 0x02U, 0x44U, 0x20U, 0x02U, 0x20U, 0x00U, 0x3AU,
0x00U, 0x00U, 0x20U, 0x01U, 0x29U, 0x03U, 0x48U, 0x42U, 0x10U, 0x88U,
0x42U, 0xFFU, 0x01U, 0x83U, 0xA7U, 0x21U, 0x00U, 0x20U, 0x01U, 0x20U,
0x01U, 0x28U, 0x02U, 0x44U, 0x22U, 0x02U, 0x41U, 0x01U, 0x6AU, 0x36U,
0x02U, 0x44U, 0x20U, 0x02U, 0x20U, 0x00U, 0x3AU, 0x00U, 0x00U, 0x20U,
0x01U, 0x29U, 0x03U, 0x48U, 0x42U, 0x08U, 0x88U, 0x42U, 0xFFU, 0x01U,
0x83U, 0xA7U, 0x21U, 0x00U, 0x20U, 0x01U, 0x20U, 0x01U, 0x28U, 0x02U,
0x44U, 0x22U, 0x02U, 0x41U, 0x01U, 0x6AU, 0x36U, 0x02U, 0x44U, 0x20U,
0x02U, 0x20U, 0x00U, 0x3AU, 0x00U, 0x00U, 0x20U, 0x01U, 0x29U, 0x03U,
0x48U, 0x42U, 0xFFU, 0x01U, 0x83U, 0xA7U, 0x21U, 0x00U, 0x20U, 0x01U,
0x20U, 0x01U, 0x28U, 0x02U, 0x44U, 0x22U, 0x02U, 0x41U, 0x01U, 0x6AU,
0x36U, 0x02U, 0x44U, 0x20U, 0x02U, 0x20U, 0x00U, 0x3AU, 0x00U, 0x00U,
0x41U, 0xBEU, 0x0BU, 0x41U, 0x04U, 0x41U, 0x83U, 0x80U, 0x08U, 0x10U,
0x07U, 0x42U, 0x04U, 0x51U, 0x04U, 0x40U, 0x41U, 0xBDU, 0x0BU, 0x41U,
0x2EU, 0x3AU, 0x00U, 0x00U, 0x0BU, 0x41U, 0xD7U, 0x0CU, 0x41U, 0xF4U,
0x00U, 0x10U, 0x08U, 0x1AU, 0x20U, 0x01U, 0x41U, 0xB0U, 0x0BU, 0x41U,
0x9BU, 0x02U, 0x10U, 0x09U, 0x37U, 0x03U, 0x38U, 0x20U, 0x01U, 0x41U,
0x80U, 0x0CU, 0x36U, 0x02U, 0x34U, 0x20U, 0x01U, 0x29U, 0x03U, 0x38U,
0x42U, 0x38U, 0x87U, 0x42U, 0x3FU, 0x83U, 0x42U, 0x40U, 0x7DU, 0xA7U,
0x21U, 0x00U, 0x20U, 0x01U, 0x20U, 0x01U, 0x28U, 0x02U, 0x34U, 0x22U,
0x02U, 0x41U, 0x01U, 0x6AU, 0x36U, 0x02U, 0x34U, 0x20U, 0x02U, 0x20U,
0x00U, 0x3AU, 0x00U, 0x00U, 0x20U, 0x01U, 0x29U, 0x03U, 0x38U, 0x42U,
0x30U, 0x87U, 0x42U, 0xFFU, 0x01U, 0x83U, 0xA7U, 0x21U, 0x00U, 0x20U,
0x01U, 0x20U, 0x01U, 0x28U, 0x02U, 0x34U, 0x22U, 0x02U, 0x41U, 0x01U,
0x6AU, 0x36U, 0x02U, 0x34U, 0x20U, 0x02U, 0x20U, 0x00U, 0x3AU, 0x00U,
0x00U, 0x20U, 0x01U, 0x29U, 0x03U, 0x38U, 0x42U, 0x28U, 0x87U, 0x42U,
0xFFU, 0x01U, 0x83U, 0xA7U, 0x21U, 0x00U, 0x20U, 0x01U, 0x20U, 0x01U,
0x28U, 0x02U, 0x34U, 0x22U, 0x02U, 0x41U, 0x01U, 0x6AU, 0x36U, 0x02U,
0x34U, 0x20U, 0x02U, 0x20U, 0x00U, 0x3AU, 0x00U, 0x00U, 0x20U, 0x01U,
0x29U, 0x03U, 0x38U, 0x42U, 0x20U, 0x87U, 0x42U, 0xFFU, 0x01U, 0x83U,
0xA7U, 0x21U, 0x00U, 0x20U, 0x01U, 0x20U, 0x01U, 0x28U, 0x02U, 0x34U,
0x22U, 0x02U, 0x41U, 0x01U, 0x6AU, 0x36U, 0x02U, 0x34U, 0x20U, 0x02U,
0x20U, 0x00U, 0x3AU, 0x00U, 0x00U, 0x20U, 0x01U, 0x29U, 0x03U, 0x38U,
0x42U, 0x18U, 0x87U, 0x42U, 0xFFU, 0x01U, 0x83U, 0xA7U, 0x21U, 0x00U,
0x20U, 0x01U, 0x20U, 0x01U, 0x28U, 0x02U, 0x34U, 0x22U, 0x02U, 0x41U,
0x01U, 0x6AU, 0x36U, 0x02U, 0x34U, 0x20U, 0x02U, 0x20U, 0x00U, 0x3AU,
0x00U, 0x00U, 0x20U, 0x01U, 0x29U, 0x03U, 0x38U, 0x42U, 0x10U, 0x87U,
0x42U, 0xFFU, 0x01U, 0x83U, 0xA7U, 0x21U, 0x00U, 0x20U, 0x01U, 0x20U,
0x01U, 0x28U, 0x02U, 0x34U, 0x22U, 0x02U, 0x41U, 0x01U, 0x6AU, 0x36U,
0x02U, 0x34U, 0x20U, 0x02U, 0x20U, 0x00U, 0x3AU, 0x00U, 0x00U, 0x20U,
0x01U, 0x29U, 0x03U, 0x38U, 0x42U, 0x08U, 0x87U, 0x42U, 0xFFU, 0x01U,
0x83U, 0xA7U, 0x21U, 0x00U, 0x20U, 0x01U, 0x20U, 0x01U, 0x28U, 0x02U,
0x34U, 0x22U, 0x02U, 0x41U, 0x01U, 0x6AU, 0x36U, 0x02U, 0x34U, 0x20U,
0x02U, 0x20U, 0x00U, 0x3AU, 0x00U, 0x00U, 0x20U, 0x01U, 0x29U, 0x03U,
0x38U, 0x42U, 0xFFU, 0x01U, 0x83U, 0xA7U, 0x21U, 0x00U, 0x20U, 0x01U,
0x20U, 0x01U, 0x28U, 0x02U, 0x34U, 0x22U, 0x02U, 0x41U, 0x01U, 0x6AU,
0x36U, 0x02U, 0x34U, 0x20U, 0x02U, 0x20U, 0x00U, 0x3AU, 0x00U, 0x00U,
0x41U, 0xAFU, 0x08U, 0x41U, 0x03U, 0x41U, 0xB0U, 0x0BU, 0x41U, 0x9BU,
0x02U, 0x41U, 0x01U, 0x10U, 0x00U, 0x1AU, 0x20U, 0x01U, 0x20U, 0x01U,
0x41U, 0x10U, 0x6AU, 0x41U, 0x20U, 0x41U, 0xB0U, 0x0BU, 0x41U, 0x9BU,
0x02U, 0x10U, 0x0AU, 0x37U, 0x03U, 0x08U, 0x41U, 0x80U, 0x08U, 0x41U,
0x0BU, 0x20U, 0x01U, 0x29U, 0x03U, 0x08U, 0x10U, 0x04U, 0x1AU, 0x20U,
0x01U, 0x20U, 0x01U, 0x29U, 0x03U, 0x58U, 0x42U, 0x01U, 0x7CU, 0x37U,
0x03U, 0x58U, 0x0CU, 0x01U, 0x0BU, 0x0BU, 0x41U, 0xF0U, 0x0AU, 0x41U,
0x17U, 0x42U, 0x86U, 0x01U, 0x10U, 0x0BU, 0x1AU, 0x20U, 0x01U, 0x41U,
0x80U, 0x01U, 0x6AU, 0x24U, 0x00U, 0x42U, 0x00U, 0x0BU, 0x0BU, 0xA6U,
0x04U, 0x04U, 0x00U, 0x41U, 0x80U, 0x08U, 0x0BU, 0xAEU, 0x03U, 0x65U,
0x6DU, 0x69U, 0x74U, 0x5FU, 0x72U, 0x65U, 0x73U, 0x75U, 0x6CU, 0x74U,
0x00U, 0x72U, 0x4BU, 0x77U, 0x58U, 0x70U, 0x69U, 0x48U, 0x47U, 0x63U,
0x51U, 0x53U, 0x7AU, 0x4BU, 0x45U, 0x47U, 0x58U, 0x63U, 0x77U, 0x65U,
0x6AU, 0x35U, 0x45U, 0x71U, 0x32U, 0x43U, 0x51U, 0x74U, 0x4EU, 0x36U,
0x48U, 0x6FU, 0x54U, 0x44U, 0x72U, 0x00U, 0x74U, 0x78U, 0x6EU, 0x00U,
0x72U, 0x47U, 0x31U, 0x51U, 0x51U, 0x76U, 0x32U, 0x6EU, 0x68U, 0x32U,
0x67U, 0x72U, 0x37U, 0x52U, 0x43U, 0x5AU, 0x31U, 0x50U, 0x38U, 0x59U,
0x59U, 0x63U, 0x42U, 0x55U, 0x4BU, 0x43U, 0x43U, 0x4EU, 0x36U, 0x33U,
0x33U, 0x6AU, 0x43U, 0x6EU, 0x00U, 0x69U, 0x00U, 0x72U, 0x4CU, 0x38U,
0x78U, 0x65U, 0x51U, 0x53U, 0x47U, 0x78U, 0x54U, 0x6DU, 0x4BU, 0x58U,
0x58U, 0x79U, 0x4CU, 0x55U, 0x46U, 0x52U, 0x75U, 0x41U, 0x41U, 0x4BU,
0x73U, 0x57U, 0x4DU, 0x59U, 0x31U, 0x42U, 0x4DU, 0x70U, 0x51U, 0x62U,
0x65U, 0x00U, 0x72U, 0x48U, 0x34U, 0x4BU, 0x45U, 0x63U, 0x47U, 0x39U,
0x64U, 0x45U, 0x77U, 0x47U, 0x77U, 0x70U, 0x6EU, 0x36U, 0x41U, 0x79U,
0x6FU, 0x57U, 0x4BU, 0x39U, 0x63U, 0x5AU, 0x50U, 0x4CU, 0x4CU, 0x34U,
0x52U, 0x4CU, 0x53U, 0x6DU, 0x57U, 0x57U, 0x00U, 0x72U, 0x68U, 0x57U,
0x35U, 0x68U, 0x67U, 0x32U, 0x78U, 0x45U, 0x37U, 0x77U, 0x32U, 0x65U,
0x77U, 0x65U, 0x70U, 0x62U, 0x68U, 0x57U, 0x74U, 0x67U, 0x5AU, 0x57U,
0x57U, 0x38U, 0x53U, 0x75U, 0x4EU, 0x36U, 0x75U, 0x57U, 0x39U, 0x37U,
0x53U, 0x00U, 0x72U, 0x4DU, 0x63U, 0x58U, 0x75U, 0x59U, 0x73U, 0x51U,
0x33U, 0x4DU, 0x6AU, 0x46U, 0x65U, 0x52U, 0x52U, 0x71U, 0x69U, 0x31U,
0x47U, 0x76U, 0x61U, 0x73U, 0x4AU, 0x7AU, 0x54U, 0x64U, 0x4CU, 0x37U,
0x77U, 0x75U, 0x4CU, 0x33U, 0x68U, 0x4EU, 0x00U, 0x72U, 0x50U, 0x4DU,
0x68U, 0x37U, 0x50U, 0x69U, 0x39U, 0x63U, 0x74U, 0x36U, 0x39U, 0x39U,
0x69U, 0x5AU, 0x55U, 0x54U, 0x57U, 0x61U, 0x79U, 0x74U, 0x4AU, 0x55U,
0x6FU, 0x48U, 0x63U, 0x4AU, 0x37U, 0x63U, 0x67U, 0x79U, 0x7AU, 0x69U,
0x4BU, 0x00U, 0x72U, 0x70U, 0x67U, 0x67U, 0x78U, 0x47U, 0x73U, 0x34U,
0x79U, 0x46U, 0x61U, 0x46U, 0x45U, 0x47U, 0x54U, 0x68U, 0x78U, 0x42U,
0x45U, 0x62U, 0x68U, 0x69U, 0x72U, 0x37U, 0x54U, 0x39U, 0x46U, 0x62U,
0x35U, 0x4CU, 0x51U, 0x4BU, 0x4CU, 0x43U, 0x00U, 0x72U, 0x44U, 0x76U,
0x4AU, 0x64U, 0x79U, 0x4AU, 0x58U, 0x45U, 0x4DU, 0x63U, 0x4CU, 0x42U,
0x79U, 0x59U, 0x37U, 0x79U, 0x38U, 0x66U, 0x50U, 0x58U, 0x4BU, 0x6EU,
0x4BU, 0x36U, 0x67U, 0x39U, 0x42U, 0x70U, 0x41U, 0x79U, 0x68U, 0x62U,
0x39U, 0x00U, 0x72U, 0x47U, 0x57U, 0x43U, 0x31U, 0x34U, 0x79U, 0x54U,
0x33U, 0x55U, 0x38U, 0x62U, 0x6BU, 0x75U, 0x41U, 0x78U, 0x32U, 0x63U,
0x38U, 0x74U, 0x41U, 0x31U, 0x61U, 0x6AU, 0x4CU, 0x55U, 0x4AU, 0x43U,
0x61U, 0x6EU, 0x64U, 0x70U, 0x35U, 0x39U, 0x00U, 0x65U, 0x6DU, 0x69U,
0x74U, 0x74U, 0x65U, 0x6EU, 0x2EU, 0x63U, 0x3AU, 0x20U, 0x53U, 0x75U,
0x63U, 0x63U, 0x65U, 0x73U, 0x73U, 0x66U, 0x75U, 0x6CU, 0x2EU, 0x00U,
0x65U, 0x6DU, 0x69U, 0x74U, 0x74U, 0x65U, 0x6EU, 0x2EU, 0x63U, 0x3AU,
0x20U, 0x43U, 0x61U, 0x6CU, 0x6CU, 0x65U, 0x64U, 0x2EU, 0x00U, 0x22U,
0x65U, 0x6DU, 0x69U, 0x74U, 0x74U, 0x65U, 0x6EU, 0x2EU, 0x63U, 0x3AU,
0x20U, 0x43U, 0x61U, 0x6CU, 0x6CU, 0x65U, 0x64U, 0x2EU, 0x22U, 0x00U,
0x41U, 0xB0U, 0x0BU, 0x0BU, 0x5AU, 0x12U, 0x00U, 0x00U, 0x22U, 0x80U,
0x00U, 0x00U, 0x00U, 0x24U, 0x00U, 0x00U, 0x00U, 0x00U, 0x99U, 0x99U,
0x99U, 0x99U, 0x99U, 0x20U, 0x1AU, 0x00U, 0x00U, 0x00U, 0x00U, 0x20U,
0x1BU, 0x00U, 0x00U, 0x00U, 0x00U, 0x61U, 0x99U, 0x99U, 0x99U, 0x99U,
0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U,
0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U,
0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U,
0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U,
0x99U, 0x99U, 0x99U, 0x99U, 0x68U, 0x40U, 0x00U, 0x00U, 0x00U, 0x00U,
0x00U, 0x00U, 0x00U, 0x73U, 0x21U, 0x00U, 0x41U, 0xABU, 0x0CU, 0x0BU,
0x02U, 0x81U, 0x14U, 0x00U, 0x41U, 0xC1U, 0x0CU, 0x0BU, 0x02U, 0x83U,
0x14U};
const std::vector<uint8_t> TshHook = {
0x00U, 0x61U, 0x73U, 0x6DU, 0x01U, 0x00U, 0x00U, 0x00U, 0x01U, 0x28U,
0x06U, 0x60U, 0x05U, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x01U, 0x7EU,
@@ -5140,347 +4931,6 @@ private:
}
}
// Remit
// | otxn | tsh | remit w/amt |
// | A | A | S |
// | A | D | S |
// | A | I | W |
// | otxn | tsh | burnable | remit w/uri |
// | A | I | F | W |
// | A | I | T | S |
void
testRemitTSH(FeatureBitset features)
{
testcase("remit tsh");
using namespace test::jtx;
using namespace std::literals;
/*
sfAmounts
*/
// otxn: account
// tsh account
// w/s: strong
for (bool const testStrong : {true, false})
{
test::jtx::Env env{
*this,
network::makeNetworkConfig(21337, "10", "1000000", "200000"),
features};
auto const account = Account("alice");
auto const dest = Account{"bob"};
env.fund(XRP(1000), account, dest);
env.close();
// set tsh collect
if (!testStrong)
addWeakTSH(env, account);
// set tsh hook
setTSHHook(env, account, testStrong);
// payment
env(remit::remit(account, dest), fee(XRP(1)), ter(tesSUCCESS));
env.close();
// verify tsh hook triggered
testTSHStrongWeak(env, tshSTRONG, __LINE__);
}
// otxn: account
// tsh dest
// w/s: strong
for (bool const testStrong : {true, false})
{
test::jtx::Env env{
*this,
network::makeNetworkConfig(21337, "10", "1000000", "200000"),
features};
auto const account = Account("alice");
auto const dest = Account{"bob"};
env.fund(XRP(1000), account, dest);
env.close();
// set tsh collect
if (!testStrong)
addWeakTSH(env, dest);
// set tsh hook
setTSHHook(env, dest, testStrong);
// payment
env(remit::remit(account, dest), fee(XRP(1)), ter(tesSUCCESS));
env.close();
// verify tsh hook triggered
testTSHStrongWeak(env, tshSTRONG, __LINE__);
}
// otxn: account
// tsh inform
// w/s: weak
for (bool const testStrong : {true, false})
{
test::jtx::Env env{
*this,
network::makeNetworkConfig(21337, "10", "1000000", "200000"),
features};
auto const account = Account("alice");
auto const dest = Account("bob");
auto const inform = Account("carol");
env.fund(XRP(1000), account, dest, inform);
env.close();
// set tsh collect
if (!testStrong)
addWeakTSH(env, inform);
// set tsh hook
setTSHHook(env, inform, testStrong);
// payment
env(remit::remit(account, dest),
remit::inform(inform),
fee(XRP(1)),
ter(tesSUCCESS));
env.close();
// verify tsh hook triggered
auto const expected = testStrong ? tshNONE : tshWEAK;
testTSHStrongWeak(env, expected, __LINE__);
}
/*
sfURITokenIDs
*/
// otxn: account
// tsh issuer
// burnable: true
// w/s: strong
for (bool const testStrong : {true, false})
{
test::jtx::Env env{
*this,
network::makeNetworkConfig(21337, "10", "1000000", "200000"),
features};
auto const account = Account("alice");
auto const dest = Account("bob");
auto const issuer = Account("carol");
env.fund(XRP(1000), account, dest, issuer);
env.close();
// mint uritoken
std::string const uri(maxTokenURILength, '?');
auto const tid = uritoken::tokenid(issuer, uri);
env(uritoken::mint(issuer, uri),
txflags(tfBurnable),
ter(tesSUCCESS));
// sell uritoken
env(uritoken::sell(issuer, strHex(tid)),
uritoken::amt(XRP(1)),
uritoken::dest(account),
ter(tesSUCCESS));
env.close();
// buy uritoken
env(uritoken::buy(account, strHex(tid)),
uritoken::amt(XRP(1)),
ter(tesSUCCESS));
env.close();
// set tsh collect
if (!testStrong)
addWeakTSH(env, issuer);
// set tsh hook
setTSHHook(env, issuer, testStrong);
// payment
env(remit::remit(account, dest),
remit::token_ids({strHex(tid)}),
fee(XRP(1)),
ter(tesSUCCESS));
env.close();
// verify tsh hook triggered
auto const expected = testStrong ? tshSTRONG : tshSTRONG;
testTSHStrongWeak(env, expected, __LINE__);
}
// otxn: account
// tsh issuer
// burnable: false
// w/s: weak
for (bool const testStrong : {true, false})
{
test::jtx::Env env{
*this,
network::makeNetworkConfig(21337, "10", "1000000", "200000"),
features};
auto const account = Account("alice");
auto const dest = Account("bob");
auto const issuer = Account("carol");
env.fund(XRP(1000), account, dest, issuer);
env.close();
// mint uritoken
std::string const uri(maxTokenURILength, '?');
auto const tid = uritoken::tokenid(issuer, uri);
env(uritoken::mint(issuer, uri), ter(tesSUCCESS));
// sell uritoken
env(uritoken::sell(issuer, strHex(tid)),
uritoken::amt(XRP(1)),
uritoken::dest(account),
ter(tesSUCCESS));
env.close();
// buy uritoken
env(uritoken::buy(account, strHex(tid)),
uritoken::amt(XRP(1)),
ter(tesSUCCESS));
env.close();
// set tsh collect
if (!testStrong)
addWeakTSH(env, issuer);
// set tsh hook
setTSHHook(env, issuer, testStrong);
// payment
env(remit::remit(account, dest),
remit::token_ids({strHex(tid)}),
fee(XRP(1)),
ter(tesSUCCESS));
env.close();
// verify tsh hook triggered
auto const expected = testStrong ? tshNONE : tshWEAK;
testTSHStrongWeak(env, expected, __LINE__);
}
}
void
testEmissionOrdering(FeatureBitset features)
{
testcase("emission ordering");
using namespace test::jtx;
using namespace std::literals;
test::jtx::Env env{
*this,
network::makeNetworkConfig(21337, "10", "1000000", "200000"),
features};
auto const alice = Account("alice");
auto const bob = Account("bob");
auto const carol = Account("carol");
auto const dave = Account("dave");
auto const elsa = Account("elsa");
auto const frank = Account("frank");
auto const grace = Account("grace");
auto const heidi = Account("heidi");
auto const ivan = Account("ivan");
auto const judy = Account("judy");
env.fund(
XRP(1000),
alice,
bob,
carol,
dave,
elsa,
frank,
grace,
heidi,
ivan,
judy);
env.close();
// set tsh hook
env(hook(alice, {{hso(EmitTenHook, overrideFlag)}}, 0),
fee(XRP(2)),
ter(tesSUCCESS));
env.close();
// invoke
env(invoke::invoke(alice), fee(XRP(2)), ter(tesSUCCESS));
env.close();
// validate the emitted txn ids
std::vector<std::string> const txIds = {
"9610F73CDD6590EB6B3C82E5EC55D4B4C80CD7128B98AA556F7EC9DD96AE7056",
"2F4582A29272390C0C25A80D4A3BCE5A14ACE6D86D8D0CB2C57719EB6FA881AE",
"89A301CFEF0DD781AB9032A6A2DCE0937BC0119D2CDD06033B8B2FD80968E519",
"DD8721B59024E168480B4DF8F8E93778601F0BD2E77FC991F3DA1182F5AD8B1E",
"5D735C2EE3CB8289F8E11621FDC9565F9D6D67F3AE59D65332EACE591D67945F",
"F02470E01731C968881AF4CBDEC90BB9E1F7AB0BE1CC22AF15451FB6D191096D",
"8AD65E541DECD49B1693F8C17DFD8A2B906F49C673C4FD2034FF772E2BE50C30",
"9F225229059CCC6257814D03C107884CF588C1C246A89ADFC16E50DF671B834C",
"13C2A54A14BADF3648CED05175E1CCAD713F7E5EA56D9735CF8813CD5551F281",
"87C60F41A96554587CED289F83F52DEE3CF670EEB189B067E6066B9A06056ADF",
};
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 emissions = meta[sfHookEmissions.jsonName];
for (size_t i = 0; i <= 9; i++)
{
auto const emitted = emissions[i][sfHookEmission.jsonName];
BEAST_EXPECT(emitted[sfEmittedTxnID.jsonName] == txIds[i]);
}
env.close();
// NOTE: emitted txns are emitted in reverse
// LIFO: Last In First Out
std::vector<jtx::Account> const accounts = {
judy,
ivan,
heidi,
grace,
frank,
elsa,
dave,
carol,
bob,
alice,
};
// verify emitted txns
for (size_t i = 0; i <= 9; i++)
{
Json::Value params;
params[jss::transaction] = txIds[i];
auto const jrr = env.rpc("json", "tx", to_string(params));
auto const meta = jrr[jss::result][jss::meta];
for (auto const& node : meta[sfAffectedNodes.jsonName])
{
auto const nodeType = node[sfLedgerEntryType.jsonName];
if (nodeType == ltEMITTED_TXN)
{
auto const& nf = node[sfFinalFields.jsonName];
auto const& et = nf[sfEmittedTxn.jsonName];
BEAST_EXPECT(
et[sfDestination.jsonName] == accounts[i].human());
break;
}
}
}
}
void
testTSH(FeatureBitset features)
{
@@ -5515,7 +4965,6 @@ private:
testURITokenBuyTSH(features);
testURITokenCancelSellOfferTSH(features);
testURITokenCreateSellOfferTSH(features);
testRemitTSH(features);
}
void
@@ -5523,7 +4972,6 @@ private:
{
testEmittedTxnReliability(features);
testEmittedFlags(features);
testEmissionOrdering(features);
}
public:

View File

@@ -362,7 +362,6 @@ struct URIToken_test : public beast::unit_test::suite
// tecNO_PERMISSION - no permission
env(uritoken::burn(carol, hexid), ter(tecNO_PERMISSION));
env.close();
// tefBAD_LEDGER - could not remove object
}
@@ -455,7 +454,10 @@ struct URIToken_test : public beast::unit_test::suite
using namespace std::literals::chrono_literals;
// setup env
Env env{*this, envconfig(), features, nullptr};
Env env{
*this, envconfig(), features, nullptr, beast::severities::kWarning
// beast::severities::kTrace
};
auto const alice = Account("alice");
auto const bob = Account("bob");
auto const carol = Account("carol");
@@ -506,7 +508,7 @@ struct URIToken_test : public beast::unit_test::suite
ter(temBAD_CURRENCY));
env.close();
// tecINSUFFICIENT_PAYMENT - insufficient buy offer amount
// tecINSUFFICIENT_PAYMENT - insuficient buy offer amount
env(uritoken::buy(bob, hexid),
uritoken::amt(USD(9)),
ter(tecINSUFFICIENT_PAYMENT));
@@ -516,13 +518,10 @@ struct URIToken_test : public beast::unit_test::suite
env(uritoken::sell(alice, hexid), uritoken::amt(XRP(10000)));
env.close();
// tecINSUFFICIENT_FUNDS - insufficient xrp - fees
// fixXahauV1 - fix checking wrong account for insufficient xrp
env(pay(env.master, alice, XRP(10000)));
auto const txResult = env.current()->rules().enabled(fixXahauV1)
? ter(tecINSUFFICIENT_FUNDS)
: ter(tecINTERNAL);
env(uritoken::buy(bob, hexid), uritoken::amt(XRP(10000)), txResult);
// tecINSUFFICIENT_FUNDS - insuficient xrp - fees
env(uritoken::buy(bob, hexid),
uritoken::amt(XRP(1000)),
ter(tecINSUFFICIENT_PAYMENT));
env.close();
// clear sell and reset new sell
@@ -530,10 +529,10 @@ struct URIToken_test : public beast::unit_test::suite
env(uritoken::sell(alice, hexid), uritoken::amt(USD(10000)));
env.close();
// tecINSUFFICIENT_FUNDS - insufficient amount
// tecINSUFFICIENT_FUNDS - insuficient amount
env(uritoken::buy(bob, hexid),
uritoken::amt(USD(10000)),
ter(tecINSUFFICIENT_FUNDS));
uritoken::amt(USD(1000)),
ter(tecINSUFFICIENT_PAYMENT));
env.close();
//----------------------------------------------------------------------
@@ -572,18 +571,15 @@ struct URIToken_test : public beast::unit_test::suite
env(uritoken::sell(alice, hexid), uritoken::amt(XRP(1000)));
env.close();
// tecINSUFFICIENT_PAYMENT - insufficient xrp sent
// tecINSUFFICIENT_PAYMENT - insuficient xrp sent
env(uritoken::buy(bob, hexid),
uritoken::amt(XRP(900)),
ter(tecINSUFFICIENT_PAYMENT));
env.close();
// tecINSUFFICIENT_FUNDS - insufficient xrp - fees
// fixXahauV1 - fix checking wrong account for insufficient xrp
auto const txResult1 = env.current()->rules().enabled(fixXahauV1)
? ter(tecINSUFFICIENT_FUNDS)
: ter(tecINTERNAL);
env(uritoken::buy(bob, hexid), uritoken::amt(XRP(1000)), txResult1);
// tecINSUFFICIENT_FUNDS - insuficient xrp - fees
env(uritoken::buy(bob, hexid),
uritoken::amt(XRP(1000)),
ter(tecINSUFFICIENT_FUNDS));
env.close();
// clear sell and set usd sell
@@ -591,19 +587,18 @@ struct URIToken_test : public beast::unit_test::suite
env(uritoken::sell(alice, hexid), uritoken::amt(USD(1000)));
env.close();
// tecINSUFFICIENT_PAYMENT - insufficient amount sent
// tecINSUFFICIENT_PAYMENT - insuficient amount sent
env(uritoken::buy(bob, hexid),
uritoken::amt(USD(900)),
ter(tecINSUFFICIENT_PAYMENT));
env.close();
// tecINSUFFICIENT_FUNDS - insufficient amount sent
// tecINSUFFICIENT_FUNDS - insuficient amount sent
env(uritoken::buy(bob, hexid),
uritoken::amt(USD(10000)),
ter(tecINSUFFICIENT_FUNDS));
env.close();
// tecNO_LINE_INSUF_RESERVE - insufficient xrp to create line
// tecNO_LINE_INSUF_RESERVE - insuficient xrp to create line
{
// fund echo 251 xrp (not enough for line reserve)
env.fund(XRP(251), echo);
@@ -622,7 +617,7 @@ struct URIToken_test : public beast::unit_test::suite
env(uritoken::sell(echo, hexid), uritoken::amt(USD(1)));
env.close();
// tecNO_LINE_INSUF_RESERVE - insufficient xrp to create line
// tecNO_LINE_INSUF_RESERVE - insuficient xrp to create line
auto const txResult = env.current()->rules().enabled(fixXahauV1)
? ter(tecINSUF_RESERVE_SELLER)
: ter(tecNO_LINE_INSUF_RESERVE);
@@ -1979,16 +1974,13 @@ struct URIToken_test : public beast::unit_test::suite
std::string multiply;
std::string divide;
};
std::array<TestRateData, 9> testCases = {{
std::array<TestRateData, 6> testCases = {{
{1, USD(100), "1100", "1100"},
{1.1, USD(100), "1110", "1090.909090909091"},
{1.0005, USD(100), "1100.05", "1099.950024987506"},
{1.005, USD(100), "1100.4999999", "1099.502487661197"},
{1.25, USD(100), "1125", "1080"},
{2, USD(100), "1200", "1050"},
{1.25, USD(1), "1001.25", "1000.8"},
{1.25, USD(0.1), "1000.125", "1000.08"},
{1.25, USD(0.0001), "1000.000125", "1000.00008"},
}};
for (auto const& tc : testCases)
@@ -2009,13 +2001,14 @@ struct URIToken_test : public beast::unit_test::suite
// setup mint
std::string const uri(maxTokenURILength, '?');
std::string const id{strHex(uritoken::tokenid(alice, uri))};
auto const delta = tc.delta;
auto const delta = USD(100);
env(uritoken::mint(alice, uri));
env(uritoken::sell(alice, id), uritoken::amt(delta));
env.close();
env(uritoken::buy(bob, id), uritoken::amt(delta));
env.close();
auto xferRate = transferRate(*env.current(), gw);
auto const postAlice = env.balance(alice, USD.issue());
if (!env.current()->rules().enabled(fixXahauV1))
{
@@ -2028,52 +2021,6 @@ struct URIToken_test : public beast::unit_test::suite
BEAST_EXPECT(env.balance(bob, USD.issue()) == preBob - delta);
}
// test dust amount
{
Env env{*this, features};
env.fund(XRP(10000), alice, bob, gw);
env(rate(gw, 1.50));
env.close();
env.trust(USD(100000), alice, bob);
env.close();
env(pay(gw, alice, USD(1000)));
env(pay(gw, bob, USD(1000)));
env.close();
auto const preAlice = env.balance(alice, USD.issue());
auto const preBob = env.balance(bob, USD.issue());
// setup mint
std::string const uri(maxTokenURILength, '?');
std::string const id{strHex(uritoken::tokenid(alice, uri))};
env(uritoken::mint(alice, uri));
auto sellTx = uritoken::sell(alice, id);
sellTx[jss::Amount][jss::issuer] = gw.human();
sellTx[jss::Amount][jss::currency] = "USD";
sellTx[jss::Amount][jss::value] = "1e-81";
env(sellTx);
env.close();
auto buyTx = uritoken::buy(bob, id);
buyTx[jss::Amount][jss::issuer] = gw.human();
buyTx[jss::Amount][jss::currency] = "USD";
buyTx[jss::Amount][jss::value] = "1e-81";
env(buyTx);
env.close();
auto const postAlice = env.balance(alice, USD.issue());
if (!env.current()->rules().enabled(fixXahauV1))
{
BEAST_EXPECT(postAlice.value() == preAlice);
}
else
{
BEAST_EXPECT(postAlice.value() == preAlice);
}
BEAST_EXPECT(env.balance(bob, USD.issue()) == preBob - USD(0));
}
// test rate change
{
Env env{*this, features};

View File

@@ -26,18 +26,13 @@ namespace jtx {
namespace remit {
Json::Value
remit(
jtx::Account const& account,
jtx::Account const& dest,
std::optional<std::uint32_t> const& dstTag)
remit(jtx::Account const& account, jtx::Account const& dest)
{
using namespace jtx;
Json::Value jv;
jv[jss::TransactionType] = jss::Remit;
jv[jss::Account] = account.human();
jv[jss::Destination] = dest.human();
if (dstTag)
jv[sfDestinationTag.jsonName] = *dstTag;
return jv;
}
@@ -69,10 +64,10 @@ inform::operator()(Env& env, JTx& jt) const
void
token_ids::operator()(Env& env, JTx& jt) const
{
jt.jv[sfURITokenIDs.jsonName] = Json::arrayValue;
for (std::size_t i = 0; i < token_ids_.size(); ++i)
{
jt.jv[sfURITokenIDs.jsonName].append(token_ids_[i]);
jt.jv[sfURITokenIDs.jsonName] = Json::arrayValue;
jt.jv[sfURITokenIDs.jsonName][i] = token_ids_[i];
}
}
@@ -81,14 +76,7 @@ uri::operator()(Env& env, JTx& jt) const
{
jt.jv[sfMintURIToken.jsonName] = Json::Value{};
jt.jv[sfMintURIToken.jsonName][sfURI.jsonName] = strHex(uri_);
if (flags_)
{
jt.jv[sfMintURIToken.jsonName][sfFlags.jsonName] = *flags_;
}
if (digest_)
{
jt.jv[sfMintURIToken.jsonName][sfDigest.fieldName] = *digest_;
}
;
}
} // namespace remit

View File

@@ -31,10 +31,7 @@ namespace jtx {
namespace remit {
Json::Value
remit(
jtx::Account const& account,
jtx::Account const& dest,
std::optional<std::uint32_t> const& dstTag = std::nullopt);
remit(jtx::Account const& account, jtx::Account const& dest);
/** Sets the optional Amount on a JTx. */
class amts
@@ -88,8 +85,7 @@ private:
std::vector<std::string> token_ids_;
public:
explicit token_ids(std::vector<std::string> const& token_ids)
: token_ids_(token_ids)
explicit token_ids(std::vector<std::string> const& token_ids) : token_ids_(token_ids)
{
}
@@ -102,15 +98,9 @@ class uri
{
private:
std::string uri_;
std::optional<std::uint32_t> flags_;
std::optional<std::string> digest_;
public:
explicit uri(
std::string const& uri,
std::optional<std::uint32_t> const& flags = std::nullopt,
std::optional<std::string> const& digest = std::nullopt)
: uri_(uri), flags_(flags), digest_(digest)
explicit uri(std::string const& uri) : uri_(uri)
{
}

View File

@@ -98,7 +98,7 @@ public:
auto vCurrent = BuildInfo::getEncodedVersion();
BEAST_EXPECT(!BuildInfo::isNewerVersion(vCurrent));
auto vMax = BuildInfo::encodeSoftwareVersion("2100.12.30");
auto vMax = BuildInfo::encodeSoftwareVersion("9999.12.30");
BEAST_EXPECT(BuildInfo::isNewerVersion(vMax));
auto vRelease1 = BuildInfo::encodeSoftwareVersion("2023.1.1-release+1");

View File

@@ -546,15 +546,14 @@ public:
}
static constexpr std::
array<std::pair<std::string_view, std::uint32_t>, 5>
array<std::pair<std::string_view, std::uint32_t>, 4>
disallowIncomingFlags{
{{"disallowIncomingCheck", asfDisallowIncomingCheck},
{"disallowIncomingNFTokenOffer",
asfDisallowIncomingNFTokenOffer},
{"disallowIncomingPayChan", asfDisallowIncomingPayChan},
{"disallowIncomingTrustline",
asfDisallowIncomingTrustline},
{"disallowIncomingRemit", asfDisallowIncomingRemit}}};
asfDisallowIncomingTrustline}}};
if (features[featureDisallowIncoming])
{

View File

@@ -88,7 +88,8 @@ public:
flag == asfDisallowIncomingPayChan ||
flag == asfDisallowIncomingNFTokenOffer ||
flag == asfDisallowIncomingTrustline ||
flag == asfTshCollect || flag == asfDisallowIncomingRemit)
flag == asfTshCollect ||
flag == asfDisallowIncomingRemit)
{
// These flags are part of the DisallowIncoming amendment
// and are tested elsewhere

View File

@@ -571,15 +571,6 @@ class AccountTx_test : public beast::unit_test::suite
env.close();
}
// Remit
{
// Empty
// XAH
// USD
// URIToken Mint
// URIToken Transfer
}
// Setup is done. Look at the transactions returned by account_tx.
Json::Value params;
params[jss::account] = alice.human();

View File

@@ -1138,207 +1138,6 @@ public:
}
}
const std::vector<uint8_t> TshHook = {
0x00U, 0x61U, 0x73U, 0x6DU, 0x01U, 0x00U, 0x00U, 0x00U, 0x01U, 0x28U,
0x06U, 0x60U, 0x05U, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x01U, 0x7EU,
0x60U, 0x04U, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x01U, 0x7EU, 0x60U, 0x00U,
0x01U, 0x7EU, 0x60U, 0x03U, 0x7FU, 0x7FU, 0x7EU, 0x01U, 0x7EU, 0x60U,
0x02U, 0x7FU, 0x7FU, 0x01U, 0x7FU, 0x60U, 0x01U, 0x7FU, 0x01U, 0x7EU,
0x02U, 0x45U, 0x05U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x05U, 0x74U, 0x72U,
0x61U, 0x63U, 0x65U, 0x00U, 0x00U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x0AU,
0x6FU, 0x74U, 0x78U, 0x6EU, 0x5FU, 0x70U, 0x61U, 0x72U, 0x61U, 0x6DU,
0x00U, 0x01U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x0AU, 0x68U, 0x6FU, 0x6FU,
0x6BU, 0x5FU, 0x61U, 0x67U, 0x61U, 0x69U, 0x6EU, 0x00U, 0x02U, 0x03U,
0x65U, 0x6EU, 0x76U, 0x06U, 0x61U, 0x63U, 0x63U, 0x65U, 0x70U, 0x74U,
0x00U, 0x03U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x02U, 0x5FU, 0x67U, 0x00U,
0x04U, 0x03U, 0x02U, 0x01U, 0x05U, 0x05U, 0x03U, 0x01U, 0x00U, 0x02U,
0x06U, 0x2BU, 0x07U, 0x7FU, 0x01U, 0x41U, 0xC0U, 0x8BU, 0x04U, 0x0BU,
0x7FU, 0x00U, 0x41U, 0x80U, 0x08U, 0x0BU, 0x7FU, 0x00U, 0x41U, 0xBCU,
0x0BU, 0x0BU, 0x7FU, 0x00U, 0x41U, 0x80U, 0x08U, 0x0BU, 0x7FU, 0x00U,
0x41U, 0xC0U, 0x8BU, 0x04U, 0x0BU, 0x7FU, 0x00U, 0x41U, 0x00U, 0x0BU,
0x7FU, 0x00U, 0x41U, 0x01U, 0x0BU, 0x07U, 0x08U, 0x01U, 0x04U, 0x68U,
0x6FU, 0x6FU, 0x6BU, 0x00U, 0x05U, 0x0AU, 0x8EU, 0x84U, 0x00U, 0x01U,
0x8AU, 0x84U, 0x00U, 0x02U, 0x09U, 0x7EU, 0x05U, 0x7FU, 0x02U, 0x40U,
0x02U, 0x40U, 0x23U, 0x00U, 0x21U, 0x0AU, 0x20U, 0x0AU, 0x41U, 0x10U,
0x6BU, 0x21U, 0x0AU, 0x20U, 0x0AU, 0x24U, 0x00U, 0x20U, 0x0AU, 0x20U,
0x00U, 0x36U, 0x02U, 0x0CU, 0x41U, 0x9EU, 0x0BU, 0x41U, 0x0FU, 0x41U,
0xC1U, 0x09U, 0x41U, 0x0EU, 0x41U, 0x00U, 0x10U, 0x00U, 0x21U, 0x02U,
0x20U, 0x02U, 0x1AU, 0x20U, 0x0AU, 0x41U, 0x0BU, 0x6AU, 0x21U, 0x00U,
0x20U, 0x00U, 0x41U, 0x01U, 0x41U, 0xBDU, 0x09U, 0x41U, 0x03U, 0x10U,
0x01U, 0x21U, 0x01U, 0x20U, 0x01U, 0x42U, 0x01U, 0x51U, 0x21U, 0x00U,
0x20U, 0x00U, 0x41U, 0x01U, 0x71U, 0x21U, 0x00U, 0x20U, 0x00U, 0x45U,
0x21U, 0x00U, 0x20U, 0x00U, 0x45U, 0x21U, 0x00U, 0x0BU, 0x20U, 0x00U,
0x04U, 0x40U, 0x02U, 0x40U, 0x02U, 0x40U, 0x10U, 0x02U, 0x21U, 0x03U,
0x20U, 0x03U, 0x1AU, 0x0BU, 0x01U, 0x0BU, 0x05U, 0x01U, 0x0BU, 0x0BU,
0x02U, 0x7EU, 0x02U, 0x40U, 0x20U, 0x0AU, 0x28U, 0x02U, 0x0CU, 0x21U,
0x00U, 0x02U, 0x40U, 0x02U, 0x40U, 0x02U, 0x40U, 0x02U, 0x40U, 0x02U,
0x40U, 0x20U, 0x00U, 0x0EU, 0x03U, 0x02U, 0x01U, 0x00U, 0x04U, 0x0BU,
0x02U, 0x40U, 0x02U, 0x40U, 0x02U, 0x40U, 0x41U, 0xDBU, 0x09U, 0x41U,
0xC3U, 0x00U, 0x41U, 0x80U, 0x08U, 0x41U, 0xC2U, 0x00U, 0x41U, 0x00U,
0x10U, 0x00U, 0x21U, 0x04U, 0x20U, 0x04U, 0x1AU, 0x0BU, 0x0CU, 0x06U,
0x0BU, 0x00U, 0x0BU, 0x00U, 0x0BU, 0x02U, 0x40U, 0x02U, 0x40U, 0x02U,
0x40U, 0x41U, 0x9FU, 0x0AU, 0x41U, 0x3DU, 0x41U, 0xC2U, 0x08U, 0x41U,
0x3CU, 0x41U, 0x00U, 0x10U, 0x00U, 0x21U, 0x05U, 0x20U, 0x05U, 0x1AU,
0x0BU, 0x0CU, 0x05U, 0x0BU, 0x00U, 0x0BU, 0x00U, 0x0BU, 0x02U, 0x40U,
0x02U, 0x40U, 0x02U, 0x40U, 0x41U, 0xDDU, 0x0AU, 0x41U, 0xC0U, 0x00U,
0x41U, 0xFEU, 0x08U, 0x41U, 0x3FU, 0x41U, 0x00U, 0x10U, 0x00U, 0x21U,
0x06U, 0x20U, 0x06U, 0x1AU, 0x0BU, 0x01U, 0x0BU, 0x0BU, 0x0BU, 0x0BU,
0x0BU, 0x02U, 0x7EU, 0x02U, 0x7EU, 0x41U, 0xAEU, 0x0BU, 0x41U, 0x0DU,
0x41U, 0xCFU, 0x09U, 0x41U, 0x0CU, 0x41U, 0x00U, 0x10U, 0x00U, 0x21U,
0x07U, 0x20U, 0x07U, 0x1AU, 0x20U, 0x0AU, 0x41U, 0x07U, 0x6AU, 0x21U,
0x0CU, 0x20U, 0x0CU, 0x21U, 0x00U, 0x20U, 0x0AU, 0x20U, 0x00U, 0x36U,
0x02U, 0x00U, 0x20U, 0x0AU, 0x28U, 0x02U, 0x0CU, 0x21U, 0x00U, 0x20U,
0x00U, 0xADU, 0x21U, 0x01U, 0x20U, 0x01U, 0x42U, 0x18U, 0x88U, 0x21U,
0x01U, 0x20U, 0x01U, 0x42U, 0xFFU, 0x01U, 0x83U, 0x21U, 0x01U, 0x20U,
0x01U, 0xA7U, 0x21U, 0x00U, 0x20U, 0x0AU, 0x28U, 0x02U, 0x00U, 0x21U,
0x0BU, 0x20U, 0x0BU, 0x20U, 0x00U, 0x3AU, 0x00U, 0x00U, 0x20U, 0x0AU,
0x28U, 0x02U, 0x0CU, 0x21U, 0x00U, 0x20U, 0x00U, 0xADU, 0x21U, 0x01U,
0x20U, 0x01U, 0x42U, 0x10U, 0x88U, 0x21U, 0x01U, 0x20U, 0x01U, 0x42U,
0xFFU, 0x01U, 0x83U, 0x21U, 0x01U, 0x20U, 0x01U, 0xA7U, 0x21U, 0x00U,
0x20U, 0x0AU, 0x28U, 0x02U, 0x00U, 0x21U, 0x0BU, 0x20U, 0x0BU, 0x20U,
0x00U, 0x3AU, 0x00U, 0x01U, 0x20U, 0x0AU, 0x28U, 0x02U, 0x0CU, 0x21U,
0x00U, 0x20U, 0x00U, 0xADU, 0x21U, 0x01U, 0x20U, 0x01U, 0x42U, 0x08U,
0x88U, 0x21U, 0x01U, 0x20U, 0x01U, 0x42U, 0xFFU, 0x01U, 0x83U, 0x21U,
0x01U, 0x20U, 0x01U, 0xA7U, 0x21U, 0x00U, 0x20U, 0x0AU, 0x28U, 0x02U,
0x00U, 0x21U, 0x0BU, 0x20U, 0x0BU, 0x20U, 0x00U, 0x3AU, 0x00U, 0x02U,
0x20U, 0x0AU, 0x28U, 0x02U, 0x0CU, 0x21U, 0x00U, 0x20U, 0x00U, 0xADU,
0x21U, 0x01U, 0x20U, 0x01U, 0x42U, 0x00U, 0x88U, 0x21U, 0x01U, 0x20U,
0x01U, 0x42U, 0xFFU, 0x01U, 0x83U, 0x21U, 0x01U, 0x20U, 0x01U, 0xA7U,
0x21U, 0x00U, 0x20U, 0x0AU, 0x28U, 0x02U, 0x00U, 0x21U, 0x0BU, 0x20U,
0x0BU, 0x20U, 0x00U, 0x3AU, 0x00U, 0x03U, 0x20U, 0x0CU, 0x21U, 0x00U,
0x20U, 0x00U, 0x41U, 0x04U, 0x42U, 0x1CU, 0x10U, 0x03U, 0x21U, 0x08U,
0x20U, 0x08U, 0x1AU, 0x41U, 0x01U, 0x41U, 0x01U, 0x10U, 0x04U, 0x21U,
0x0DU, 0x20U, 0x0DU, 0x1AU, 0x20U, 0x0AU, 0x41U, 0x10U, 0x6AU, 0x21U,
0x00U, 0x20U, 0x00U, 0x24U, 0x00U, 0x42U, 0x00U, 0x21U, 0x09U, 0x42U,
0x00U, 0x0BU, 0x0BU, 0x0BU, 0x0BU, 0x0BU, 0xC3U, 0x03U, 0x01U, 0x00U,
0x41U, 0x80U, 0x08U, 0x0BU, 0xBBU, 0x03U, 0x74U, 0x73U, 0x68U, 0x2EU,
0x63U, 0x3AU, 0x20U, 0x57U, 0x65U, 0x61U, 0x6BU, 0x20U, 0x41U, 0x67U,
0x61U, 0x69U, 0x6EU, 0x2EU, 0x20U, 0x45U, 0x78U, 0x65U, 0x63U, 0x75U,
0x74U, 0x65U, 0x20U, 0x41U, 0x46U, 0x54U, 0x45U, 0x52U, 0x20U, 0x74U,
0x72U, 0x61U, 0x6EU, 0x73U, 0x61U, 0x63U, 0x74U, 0x69U, 0x6FU, 0x6EU,
0x20U, 0x69U, 0x73U, 0x20U, 0x61U, 0x70U, 0x70U, 0x6CU, 0x69U, 0x65U,
0x64U, 0x20U, 0x74U, 0x6FU, 0x20U, 0x6CU, 0x65U, 0x64U, 0x67U, 0x65U,
0x72U, 0x00U, 0x74U, 0x73U, 0x68U, 0x2EU, 0x63U, 0x3AU, 0x20U, 0x57U,
0x65U, 0x61U, 0x6BU, 0x2EU, 0x20U, 0x45U, 0x78U, 0x65U, 0x63U, 0x75U,
0x74U, 0x65U, 0x20U, 0x41U, 0x46U, 0x54U, 0x45U, 0x52U, 0x20U, 0x74U,
0x72U, 0x61U, 0x6EU, 0x73U, 0x61U, 0x63U, 0x74U, 0x69U, 0x6FU, 0x6EU,
0x20U, 0x69U, 0x73U, 0x20U, 0x61U, 0x70U, 0x70U, 0x6CU, 0x69U, 0x65U,
0x64U, 0x20U, 0x74U, 0x6FU, 0x20U, 0x6CU, 0x65U, 0x64U, 0x67U, 0x65U,
0x72U, 0x00U, 0x74U, 0x73U, 0x68U, 0x2EU, 0x63U, 0x3AU, 0x20U, 0x53U,
0x74U, 0x72U, 0x6FU, 0x6EU, 0x67U, 0x2EU, 0x20U, 0x45U, 0x78U, 0x65U,
0x63U, 0x75U, 0x74U, 0x65U, 0x20U, 0x42U, 0x45U, 0x46U, 0x4FU, 0x52U,
0x45U, 0x20U, 0x74U, 0x72U, 0x61U, 0x6EU, 0x73U, 0x61U, 0x63U, 0x74U,
0x69U, 0x6FU, 0x6EU, 0x20U, 0x69U, 0x73U, 0x20U, 0x61U, 0x70U, 0x70U,
0x6CU, 0x69U, 0x65U, 0x64U, 0x20U, 0x74U, 0x6FU, 0x20U, 0x6CU, 0x65U,
0x64U, 0x67U, 0x65U, 0x72U, 0x00U, 0x41U, 0x41U, 0x57U, 0x00U, 0x74U,
0x73U, 0x68U, 0x2EU, 0x63U, 0x3AU, 0x20U, 0x53U, 0x74U, 0x61U, 0x72U,
0x74U, 0x2EU, 0x00U, 0x74U, 0x73U, 0x68U, 0x2EU, 0x63U, 0x3AU, 0x20U,
0x45U, 0x6EU, 0x64U, 0x2EU, 0x00U, 0x22U, 0x74U, 0x73U, 0x68U, 0x2EU,
0x63U, 0x3AU, 0x20U, 0x57U, 0x65U, 0x61U, 0x6BU, 0x20U, 0x41U, 0x67U,
0x61U, 0x69U, 0x6EU, 0x2EU, 0x20U, 0x45U, 0x78U, 0x65U, 0x63U, 0x75U,
0x74U, 0x65U, 0x20U, 0x41U, 0x46U, 0x54U, 0x45U, 0x52U, 0x20U, 0x74U,
0x72U, 0x61U, 0x6EU, 0x73U, 0x61U, 0x63U, 0x74U, 0x69U, 0x6FU, 0x6EU,
0x20U, 0x69U, 0x73U, 0x20U, 0x61U, 0x70U, 0x70U, 0x6CU, 0x69U, 0x65U,
0x64U, 0x20U, 0x74U, 0x6FU, 0x20U, 0x6CU, 0x65U, 0x64U, 0x67U, 0x65U,
0x72U, 0x22U, 0x00U, 0x22U, 0x74U, 0x73U, 0x68U, 0x2EU, 0x63U, 0x3AU,
0x20U, 0x57U, 0x65U, 0x61U, 0x6BU, 0x2EU, 0x20U, 0x45U, 0x78U, 0x65U,
0x63U, 0x75U, 0x74U, 0x65U, 0x20U, 0x41U, 0x46U, 0x54U, 0x45U, 0x52U,
0x20U, 0x74U, 0x72U, 0x61U, 0x6EU, 0x73U, 0x61U, 0x63U, 0x74U, 0x69U,
0x6FU, 0x6EU, 0x20U, 0x69U, 0x73U, 0x20U, 0x61U, 0x70U, 0x70U, 0x6CU,
0x69U, 0x65U, 0x64U, 0x20U, 0x74U, 0x6FU, 0x20U, 0x6CU, 0x65U, 0x64U,
0x67U, 0x65U, 0x72U, 0x22U, 0x00U, 0x22U, 0x74U, 0x73U, 0x68U, 0x2EU,
0x63U, 0x3AU, 0x20U, 0x53U, 0x74U, 0x72U, 0x6FU, 0x6EU, 0x67U, 0x2EU,
0x20U, 0x45U, 0x78U, 0x65U, 0x63U, 0x75U, 0x74U, 0x65U, 0x20U, 0x42U,
0x45U, 0x46U, 0x4FU, 0x52U, 0x45U, 0x20U, 0x74U, 0x72U, 0x61U, 0x6EU,
0x73U, 0x61U, 0x63U, 0x74U, 0x69U, 0x6FU, 0x6EU, 0x20U, 0x69U, 0x73U,
0x20U, 0x61U, 0x70U, 0x70U, 0x6CU, 0x69U, 0x65U, 0x64U, 0x20U, 0x74U,
0x6FU, 0x20U, 0x6CU, 0x65U, 0x64U, 0x67U, 0x65U, 0x72U, 0x22U, 0x00U,
0x22U, 0x74U, 0x73U, 0x68U, 0x2EU, 0x63U, 0x3AU, 0x20U, 0x53U, 0x74U,
0x61U, 0x72U, 0x74U, 0x2EU, 0x22U, 0x00U, 0x22U, 0x74U, 0x73U, 0x68U,
0x2EU, 0x63U, 0x3AU, 0x20U, 0x45U, 0x6EU, 0x64U, 0x2EU, 0x22U};
void static overrideFlag(Json::Value& jv)
{
jv[jss::Flags] = 0b00000001U;
}
void
setTSHHook(
jtx::Env& env,
jtx::Account const& account)
{
using namespace test::jtx;
env(hook(account, {{hso(TshHook, overrideFlag)}}, 0),
fee(XRP(2)),
ter(tesSUCCESS));
env.close();
}
void
testAccount(FeatureBitset features)
{
testcase("AccountWithHookStream");
using namespace std::chrono_literals;
using namespace jtx;
Env env(*this, features);
auto const alice = Account("alice");
auto const bob = Account("bob");
auto const gw = Account("gw");
auto const USD = gw["USD"];
env.fund(XRP(10000), alice, bob, gw);
env.trust(USD(20000), alice, bob);
env.close();
auto wsc = makeWSClient(env.app().config());
Json::Value stream;
{
// RPC subscribe to account stream
stream[jss::accounts] = Json::arrayValue;
stream[jss::accounts].append(bob.human());
auto jv = wsc->invoke("subscribe", stream);
if (wsc->version() == 2)
{
BEAST_EXPECT(
jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
BEAST_EXPECT(
jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
}
BEAST_EXPECT(jv[jss::result][jss::status] == "success");
}
// Test Invoke Tx
{
setTSHHook(env, bob);
// Submit and Close
env(invoke::invoke(alice), invoke::dest(bob), fee(XRP(1)), ter(tesSUCCESS));
env.close();
// Check stream update
BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) {
if (jv[jss::transaction][jss::TransactionType] == "Invoke")
return true;
return false;
}));
}
// RPC unsubscribe
auto jv = wsc->invoke("unsubscribe", stream);
if (wsc->version() == 2)
{
BEAST_EXPECT(
jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
BEAST_EXPECT(
jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
}
BEAST_EXPECT(jv[jss::status] == "success");
}
void
run() override
{
@@ -1356,7 +1155,6 @@ public:
testSubErrors(false);
testSubByUrl();
testHistoryTxStream();
testAccount(all);
}
};