mirror of
https://github.com/Xahau/xahaud.git
synced 2026-01-10 01:35:16 +00:00
Compare commits
3 Commits
fix-gh-act
...
func-hooks
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c6a27e895e | ||
|
|
b56dc38c22 | ||
|
|
e654219ba5 |
4
.github/workflows/build-in-docker.yml
vendored
4
.github/workflows/build-in-docker.yml
vendored
@@ -7,8 +7,8 @@ on:
|
||||
branches: [ "dev", "candidate", "release", "jshooks" ]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
group: ${{ github.workflow }}
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
checkout:
|
||||
|
||||
@@ -755,7 +755,6 @@ if (tests)
|
||||
src/test/app/Taker_test.cpp
|
||||
src/test/app/TheoreticalQuality_test.cpp
|
||||
src/test/app/Ticket_test.cpp
|
||||
src/test/app/Touch_test.cpp
|
||||
src/test/app/Transaction_ordering_test.cpp
|
||||
src/test/app/TrustAndBalance_test.cpp
|
||||
src/test/app/TxQ_test.cpp
|
||||
@@ -765,6 +764,7 @@ if (tests)
|
||||
src/test/app/ValidatorSite_test.cpp
|
||||
src/test/app/SetHook_test.cpp
|
||||
src/test/app/SetHookTSH_test.cpp
|
||||
src/test/app/SetHookV3_test.cpp
|
||||
src/test/app/Wildcard_test.cpp
|
||||
src/test/app/XahauGenesis_test.cpp
|
||||
src/test/app/tx/apply_test.cpp
|
||||
|
||||
@@ -30,7 +30,7 @@ fi
|
||||
perl -i -pe "s/^(\\s*)-DBUILD_SHARED_LIBS=OFF/\\1-DBUILD_SHARED_LIBS=OFF\\n\\1-DROCKSDB_BUILD_SHARED=OFF/g" Builds/CMake/deps/Rocksdb.cmake &&
|
||||
mv Builds/CMake/deps/WasmEdge.cmake Builds/CMake/deps/WasmEdge.old &&
|
||||
echo "find_package(LLVM REQUIRED CONFIG)
|
||||
message(STATUS \"Found LLVM \${LLVM_PACKAGE_VERSION}\")
|
||||
message(STATUS \"Found LLVM ${LLVM_PACKAGE_VERSION}\")
|
||||
message(STATUS \"Using LLVMConfig.cmake in: \${LLVM_DIR}\")
|
||||
add_library (wasmedge STATIC IMPORTED GLOBAL)
|
||||
set_target_properties(wasmedge PROPERTIES IMPORTED_LOCATION \${WasmEdge_LIB})
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
using GuardLog =
|
||||
std::optional<std::reference_wrapper<std::basic_ostream<char>>>;
|
||||
|
||||
#define DEBUG_GUARD 0
|
||||
#define DEBUG_GUARD_VERBOSE 0
|
||||
#define DEBUG_GUARD_VERY_VERBOSE 0
|
||||
#define DEBUG_GUARD 1
|
||||
#define DEBUG_GUARD_VERBOSE 1
|
||||
#define DEBUG_GUARD_VERY_VERBOSE 1
|
||||
|
||||
#define GUARDLOG(logCode) \
|
||||
if (!guardLog) \
|
||||
@@ -901,23 +901,23 @@ validateGuards(
|
||||
// followed by an leb128 length
|
||||
int section_type = wasm[i++];
|
||||
|
||||
if (section_type == 0)
|
||||
{
|
||||
GUARDLOG(hook::log::CUSTOM_SECTION_DISALLOWED)
|
||||
<< "Malformed transaction. "
|
||||
<< "Hook contained a custom section, which is not allowed. Use "
|
||||
"cleaner.\n";
|
||||
return {};
|
||||
}
|
||||
// if (section_type == 0)
|
||||
// {
|
||||
// GUARDLOG(hook::log::CUSTOM_SECTION_DISALLOWED)
|
||||
// << "Malformed transaction. "
|
||||
// << "Hook contained a custom section, which is not allowed. Use "
|
||||
// "cleaner.\n";
|
||||
// return {};
|
||||
// }
|
||||
|
||||
if (section_type <= last_section_type)
|
||||
{
|
||||
GUARDLOG(hook::log::SECTIONS_OUT_OF_SEQUENCE)
|
||||
<< "Malformed transcation. "
|
||||
<< "Hook contained wasm sections that were either repeated or "
|
||||
"were out of sequence.\n";
|
||||
return {};
|
||||
}
|
||||
// if (section_type <= last_section_type)
|
||||
// {
|
||||
// GUARDLOG(hook::log::SECTIONS_OUT_OF_SEQUENCE)
|
||||
// << "Malformed transcation. "
|
||||
// << "Hook contained wasm sections that were either repeated or "
|
||||
// "were out of sequence.\n";
|
||||
// return {};
|
||||
// }
|
||||
|
||||
last_section_type = section_type;
|
||||
|
||||
@@ -1139,21 +1139,32 @@ validateGuards(
|
||||
}
|
||||
}
|
||||
|
||||
if (wasm[i] == 'm' && wasm[i + 1] == 'e' && wasm[i + 2] == 't' && wasm[i + 3] == 'h' && wasm[i + 4] == 'o' && wasm[i + 5] == 'd')
|
||||
{
|
||||
i += name_len;
|
||||
CHECK_SHORT_HOOK();
|
||||
i++;
|
||||
CHECK_SHORT_HOOK();
|
||||
hook_func_idx = parseLeb128(wasm, i, &i);
|
||||
CHECK_SHORT_HOOK();
|
||||
continue;
|
||||
}
|
||||
|
||||
i += name_len + 1;
|
||||
parseLeb128(wasm, i, &i);
|
||||
CHECK_SHORT_HOOK();
|
||||
}
|
||||
|
||||
// execution to here means export section was parsed
|
||||
if (!hook_func_idx)
|
||||
{
|
||||
GUARDLOG(hook::log::EXPORT_MISSING)
|
||||
<< "Malformed transaction. "
|
||||
<< "Hook did not export: "
|
||||
<< (!hook_func_idx ? "int64_t hook(uint32_t); " : "")
|
||||
<< "\n";
|
||||
return {};
|
||||
}
|
||||
// if (!hook_func_idx)
|
||||
// {
|
||||
// GUARDLOG(hook::log::EXPORT_MISSING)
|
||||
// << "Malformed transaction. "
|
||||
// << "Hook did not export: "
|
||||
// << (!hook_func_idx ? "int64_t hook(uint32_t); " : "")
|
||||
// << "\n";
|
||||
// return {};
|
||||
// }
|
||||
}
|
||||
else if (section_type == 3) // function section
|
||||
{
|
||||
@@ -1295,13 +1306,13 @@ validateGuards(
|
||||
else
|
||||
{
|
||||
// fail
|
||||
GUARDLOG(hook::log::FUNC_TYPE_INVALID)
|
||||
<< "Invalid function type. Not used by any import or "
|
||||
"hook/cbak func. "
|
||||
<< "Codesec: " << section_type << " "
|
||||
<< "Local: " << j << " "
|
||||
<< "Offset: " << i << "\n";
|
||||
return {};
|
||||
// GUARDLOG(hook::log::FUNC_TYPE_INVALID)
|
||||
// << "Invalid function type. Not used by any import or "
|
||||
// "hook/cbak func. "
|
||||
// << "Codesec: " << section_type << " "
|
||||
// << "Local: " << j << " "
|
||||
// << "Offset: " << i << "\n";
|
||||
// return {};
|
||||
}
|
||||
|
||||
int param_count = parseLeb128(wasm, i, &i);
|
||||
@@ -1320,11 +1331,11 @@ validateGuards(
|
||||
}
|
||||
else if (param_count != (*first_signature).get().size() - 1)
|
||||
{
|
||||
GUARDLOG(hook::log::FUNC_TYPE_INVALID)
|
||||
<< "Malformed transaction. "
|
||||
<< "Hook API: " << *first_name
|
||||
<< " has the wrong number of parameters.\n";
|
||||
return {};
|
||||
// GUARDLOG(hook::log::FUNC_TYPE_INVALID)
|
||||
// << "Malformed transaction. "
|
||||
// << "Hook API: " << *first_name
|
||||
// << " has the wrong number of parameters.\n";
|
||||
// return {};
|
||||
}
|
||||
|
||||
for (int k = 0; k < param_count; ++k)
|
||||
@@ -1388,12 +1399,12 @@ validateGuards(
|
||||
// most compilers out
|
||||
if (result_count != 1)
|
||||
{
|
||||
GUARDLOG(hook::log::FUNC_RETURN_COUNT)
|
||||
<< "Malformed transaction. "
|
||||
<< "Hook declares a function type that returns fewer "
|
||||
"or more than one value. "
|
||||
<< "\n";
|
||||
return {};
|
||||
// GUARDLOG(hook::log::FUNC_RETURN_COUNT)
|
||||
// << "Malformed transaction. "
|
||||
// << "Hook declares a function type that returns fewer "
|
||||
// "or more than one value. "
|
||||
// << "\n";
|
||||
// return {};
|
||||
}
|
||||
|
||||
// this can only ever be 1 in production, but in testing it may
|
||||
|
||||
@@ -723,6 +723,9 @@ public:
|
||||
uint32_t wasmParam,
|
||||
beast::Journal const& j)
|
||||
{
|
||||
|
||||
static WasmEdge_String _hookFunctionName = WasmEdge_StringCreateByCString("methodCreate");
|
||||
|
||||
// HookExecutor can only execute once
|
||||
assert(!spent);
|
||||
|
||||
@@ -761,7 +764,7 @@ public:
|
||||
vm.ctx,
|
||||
reinterpret_cast<const uint8_t*>(wasm),
|
||||
len,
|
||||
callback ? cbakFunctionName : hookFunctionName,
|
||||
_hookFunctionName,
|
||||
params,
|
||||
1,
|
||||
returns,
|
||||
|
||||
@@ -1079,24 +1079,6 @@ Transactor::checkMultiSign(PreclaimContext const& ctx)
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// increment the touch counter on an account
|
||||
static void
|
||||
touchAccount(ApplyView& view, AccountID const& id)
|
||||
{
|
||||
if (!view.rules().enabled(featureTouch))
|
||||
return;
|
||||
|
||||
std::shared_ptr<SLE> sle = view.peek(keylet::account(id));
|
||||
if (!sle)
|
||||
return;
|
||||
|
||||
uint64_t tc =
|
||||
sle->isFieldPresent(sfTouchCount) ? sle->getFieldU64(sfTouchCount) : 0;
|
||||
|
||||
sle->setFieldU64(sfTouchCount, tc + 1);
|
||||
view.update(sle);
|
||||
}
|
||||
|
||||
static void
|
||||
removeUnfundedOffers(
|
||||
ApplyView& view,
|
||||
@@ -1537,8 +1519,6 @@ Transactor::doTSH(
|
||||
if ((!canRollback && strong) || (canRollback && !strong))
|
||||
continue;
|
||||
|
||||
touchAccount(view, tshAccountID);
|
||||
|
||||
auto klTshHook = keylet::hook(tshAccountID);
|
||||
|
||||
auto tshHook = view.read(klTshHook);
|
||||
@@ -1796,7 +1776,7 @@ Transactor::operator()()
|
||||
|
||||
// write state if all chains executed successfully
|
||||
if (isTesSuccess(result))
|
||||
hook::finalizeHookState(stateMap, ctx_, ctx_.tx.getTransactionID());
|
||||
result = hook::finalizeHookState(stateMap, ctx_, ctx_.tx.getTransactionID());
|
||||
|
||||
// write hook results
|
||||
// this happens irrespective of whether final result was a tesSUCCESS
|
||||
@@ -2051,8 +2031,9 @@ Transactor::operator()()
|
||||
for (auto const& [accID, hookHashes] : aawMap)
|
||||
doAgainAsWeak(accID, hookHashes, stateMap, weakResults, proMeta);
|
||||
|
||||
result = hook::finalizeHookState(stateMap, ctx_, ctx_.tx.getTransactionID());
|
||||
|
||||
// write hook results
|
||||
hook::finalizeHookState(stateMap, ctx_, ctx_.tx.getTransactionID());
|
||||
for (auto& weakResult : weakResults)
|
||||
hook::finalizeHookResult(weakResult, ctx_, isTesSuccess(result));
|
||||
|
||||
|
||||
@@ -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 = 78;
|
||||
static constexpr std::size_t numFeatures = 77;
|
||||
|
||||
/** Amendments that this server supports and the default voting behavior.
|
||||
Whether they are enabled depends on the Rules defined in the validated
|
||||
@@ -362,7 +362,6 @@ extern uint256 const fix240819;
|
||||
extern uint256 const fixPageCap;
|
||||
extern uint256 const fix240911;
|
||||
extern uint256 const fixFloatDivide;
|
||||
extern uint256 const featureTouch;
|
||||
extern uint256 const fixReduceImport;
|
||||
extern uint256 const fixXahauV3;
|
||||
extern uint256 const fix20250131;
|
||||
|
||||
@@ -433,7 +433,6 @@ extern SF_UINT64 const sfReferenceCount;
|
||||
extern SF_UINT64 const sfRewardAccumulator;
|
||||
extern SF_UINT64 const sfAccountCount;
|
||||
extern SF_UINT64 const sfAccountIndex;
|
||||
extern SF_UINT64 const sfTouchCount;
|
||||
|
||||
// 128-bit
|
||||
extern SF_UINT128 const sfEmailHash;
|
||||
|
||||
@@ -468,7 +468,6 @@ REGISTER_FIX (fix240819, Supported::yes, VoteBehavior::De
|
||||
REGISTER_FIX (fixPageCap, Supported::yes, VoteBehavior::DefaultYes);
|
||||
REGISTER_FIX (fix240911, Supported::yes, VoteBehavior::DefaultYes);
|
||||
REGISTER_FIX (fixFloatDivide, Supported::yes, VoteBehavior::DefaultYes);
|
||||
REGISTER_FEATURE(Touch, Supported::yes, VoteBehavior::DefaultNo);
|
||||
REGISTER_FIX (fixReduceImport, Supported::yes, VoteBehavior::DefaultYes);
|
||||
REGISTER_FIX (fixXahauV3, Supported::yes, VoteBehavior::DefaultYes);
|
||||
REGISTER_FIX (fix20250131, Supported::yes, VoteBehavior::DefaultYes);
|
||||
|
||||
@@ -66,7 +66,6 @@ LedgerFormats::LedgerFormats()
|
||||
{sfGovernanceFlags, soeOPTIONAL},
|
||||
{sfGovernanceMarks, soeOPTIONAL},
|
||||
{sfAccountIndex, soeOPTIONAL},
|
||||
{sfTouchCount, soeOPTIONAL},
|
||||
},
|
||||
commonFields);
|
||||
|
||||
|
||||
@@ -183,7 +183,6 @@ CONSTRUCT_TYPED_SFIELD(sfEmitBurden, "EmitBurden", UINT64,
|
||||
CONSTRUCT_TYPED_SFIELD(sfHookInstructionCount, "HookInstructionCount", UINT64, 17);
|
||||
CONSTRUCT_TYPED_SFIELD(sfHookReturnCode, "HookReturnCode", UINT64, 18);
|
||||
CONSTRUCT_TYPED_SFIELD(sfReferenceCount, "ReferenceCount", UINT64, 19);
|
||||
CONSTRUCT_TYPED_SFIELD(sfTouchCount, "TouchCount", UINT64, 97);
|
||||
CONSTRUCT_TYPED_SFIELD(sfAccountIndex, "AccountIndex", UINT64, 98);
|
||||
CONSTRUCT_TYPED_SFIELD(sfAccountCount, "AccountCount", UINT64, 99);
|
||||
CONSTRUCT_TYPED_SFIELD(sfRewardAccumulator, "RewardAccumulator", UINT64, 100);
|
||||
|
||||
1
src/test/app/.env
Normal file
1
src/test/app/.env
Normal file
@@ -0,0 +1 @@
|
||||
HOOKS_COMPILE_HOST=http://localhost:9000
|
||||
@@ -42,8 +42,6 @@ class Discrepancy_test : public beast::unit_test::suite
|
||||
using namespace test::jtx;
|
||||
Env env{*this, features};
|
||||
|
||||
bool const withTouch = env.current()->rules().enabled(featureTouch);
|
||||
|
||||
Account A1{"A1"};
|
||||
Account A2{"A2"};
|
||||
Account A3{"A3"};
|
||||
@@ -109,8 +107,7 @@ class Discrepancy_test : public beast::unit_test::suite
|
||||
auto meta = jrr[jss::meta];
|
||||
uint64_t sumPrev{0};
|
||||
uint64_t sumFinal{0};
|
||||
BEAST_EXPECT(
|
||||
meta[sfAffectedNodes.fieldName].size() == withTouch ? 11 : 10);
|
||||
BEAST_EXPECT(meta[sfAffectedNodes.fieldName].size() == 9);
|
||||
for (auto const& an : meta[sfAffectedNodes.fieldName])
|
||||
{
|
||||
Json::Value node;
|
||||
@@ -130,17 +127,12 @@ class Discrepancy_test : public beast::unit_test::suite
|
||||
Json::Value finalFields = node.isMember(sfFinalFields.fieldName)
|
||||
? node[sfFinalFields.fieldName]
|
||||
: node[sfNewFields.fieldName];
|
||||
|
||||
// withTouch: "Touched" account does not update Balance
|
||||
if (prevFields.isMember(sfBalance.fieldName))
|
||||
{
|
||||
if (prevFields)
|
||||
sumPrev += beast::lexicalCastThrow<std::uint64_t>(
|
||||
prevFields[sfBalance.fieldName].asString());
|
||||
if (finalFields)
|
||||
sumFinal += beast::lexicalCastThrow<std::uint64_t>(
|
||||
finalFields[sfBalance.fieldName].asString());
|
||||
}
|
||||
if (prevFields)
|
||||
sumPrev += beast::lexicalCastThrow<std::uint64_t>(
|
||||
prevFields[sfBalance.fieldName].asString());
|
||||
if (finalFields)
|
||||
sumFinal += beast::lexicalCastThrow<std::uint64_t>(
|
||||
finalFields[sfBalance.fieldName].asString());
|
||||
}
|
||||
}
|
||||
// the difference in balances (final and prev) should be the
|
||||
@@ -155,7 +147,6 @@ public:
|
||||
using namespace test::jtx;
|
||||
auto const sa = supported_amendments();
|
||||
testXRPDiscrepancy(sa - featureFlowCross);
|
||||
testXRPDiscrepancy(sa - featureTouch);
|
||||
testXRPDiscrepancy(sa);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -60,7 +60,6 @@ class Freeze_test : public beast::unit_test::suite
|
||||
|
||||
using namespace test::jtx;
|
||||
Env env(*this, features);
|
||||
bool const withTouch = env.current()->rules().enabled(featureTouch);
|
||||
|
||||
Account G1{"G1"};
|
||||
Account alice{"alice"};
|
||||
@@ -114,7 +113,7 @@ class Freeze_test : public beast::unit_test::suite
|
||||
env(trust(G1, bob["USD"](0), tfSetFreeze));
|
||||
auto affected = env.meta()->getJson(
|
||||
JsonOptions::none)[sfAffectedNodes.fieldName];
|
||||
if (!BEAST_EXPECT(checkArraySize(affected, withTouch ? 3u : 2u)))
|
||||
if (!BEAST_EXPECT(checkArraySize(affected, 2u)))
|
||||
return;
|
||||
auto ff =
|
||||
affected[1u][sfModifiedNode.fieldName][sfFinalFields.fieldName];
|
||||
@@ -132,10 +131,10 @@ class Freeze_test : public beast::unit_test::suite
|
||||
env(offer(bob, G1["USD"](5), XRP(25)));
|
||||
auto affected = env.meta()->getJson(
|
||||
JsonOptions::none)[sfAffectedNodes.fieldName];
|
||||
if (!BEAST_EXPECT(checkArraySize(affected, withTouch ? 6u : 5u)))
|
||||
if (!BEAST_EXPECT(checkArraySize(affected, 5u)))
|
||||
return;
|
||||
auto ff = affected[withTouch ? 4u : 3u][sfModifiedNode.fieldName]
|
||||
[sfFinalFields.fieldName];
|
||||
auto ff =
|
||||
affected[3u][sfModifiedNode.fieldName][sfFinalFields.fieldName];
|
||||
BEAST_EXPECT(
|
||||
ff[sfHighLimit.fieldName] ==
|
||||
bob["USD"](100).value().getJson(JsonOptions::none));
|
||||
@@ -200,7 +199,7 @@ class Freeze_test : public beast::unit_test::suite
|
||||
env(trust(G1, bob["USD"](0), tfClearFreeze));
|
||||
auto affected = env.meta()->getJson(
|
||||
JsonOptions::none)[sfAffectedNodes.fieldName];
|
||||
if (!BEAST_EXPECT(checkArraySize(affected, withTouch ? 3u : 2u)))
|
||||
if (!BEAST_EXPECT(checkArraySize(affected, 2u)))
|
||||
return;
|
||||
auto ff =
|
||||
affected[1u][sfModifiedNode.fieldName][sfFinalFields.fieldName];
|
||||
@@ -378,7 +377,6 @@ class Freeze_test : public beast::unit_test::suite
|
||||
|
||||
using namespace test::jtx;
|
||||
Env env(*this, features);
|
||||
bool const withTouch = env.current()->rules().enabled(featureTouch);
|
||||
|
||||
Account G1{"G1"};
|
||||
Account A1{"A1"};
|
||||
@@ -419,7 +417,7 @@ class Freeze_test : public beast::unit_test::suite
|
||||
env(trust(G1, A1["USD"](0), tfSetFreeze));
|
||||
auto affected =
|
||||
env.meta()->getJson(JsonOptions::none)[sfAffectedNodes.fieldName];
|
||||
if (!BEAST_EXPECT(checkArraySize(affected, withTouch ? 2u : 1u)))
|
||||
if (!BEAST_EXPECT(checkArraySize(affected, 1u)))
|
||||
return;
|
||||
|
||||
auto let =
|
||||
@@ -434,7 +432,6 @@ class Freeze_test : public beast::unit_test::suite
|
||||
|
||||
using namespace test::jtx;
|
||||
Env env(*this, features);
|
||||
bool const withTouch = env.current()->rules().enabled(featureTouch);
|
||||
|
||||
Account G1{"G1"};
|
||||
Account A2{"A2"};
|
||||
@@ -478,7 +475,7 @@ class Freeze_test : public beast::unit_test::suite
|
||||
env(trust(G1, A3["USD"](0), tfSetFreeze));
|
||||
auto affected =
|
||||
env.meta()->getJson(JsonOptions::none)[sfAffectedNodes.fieldName];
|
||||
if (!BEAST_EXPECT(checkArraySize(affected, withTouch ? 3u : 2u)))
|
||||
if (!BEAST_EXPECT(checkArraySize(affected, 2u)))
|
||||
return;
|
||||
auto ff =
|
||||
affected[1u][sfModifiedNode.fieldName][sfFinalFields.fieldName];
|
||||
@@ -508,10 +505,9 @@ class Freeze_test : public beast::unit_test::suite
|
||||
env(trust(G1, A4["USD"](0), tfSetFreeze));
|
||||
affected =
|
||||
env.meta()->getJson(JsonOptions::none)[sfAffectedNodes.fieldName];
|
||||
if (!BEAST_EXPECT(checkArraySize(affected, withTouch ? 3u : 2u)))
|
||||
if (!BEAST_EXPECT(checkArraySize(affected, 2u)))
|
||||
return;
|
||||
ff = affected[withTouch ? 1u : 0u][sfModifiedNode.fieldName]
|
||||
[sfFinalFields.fieldName];
|
||||
ff = affected[0u][sfModifiedNode.fieldName][sfFinalFields.fieldName];
|
||||
BEAST_EXPECT(
|
||||
ff[sfLowLimit.fieldName] ==
|
||||
G1["USD"](0).value().getJson(JsonOptions::none));
|
||||
@@ -525,7 +521,7 @@ class Freeze_test : public beast::unit_test::suite
|
||||
env.meta()->getJson(JsonOptions::none)[sfAffectedNodes.fieldName];
|
||||
if (!BEAST_EXPECT(checkArraySize(affected, 8u)))
|
||||
return;
|
||||
auto created = affected[5u][sfCreatedNode.fieldName];
|
||||
auto created = affected[0u][sfCreatedNode.fieldName];
|
||||
BEAST_EXPECT(
|
||||
created[sfNewFields.fieldName][jss::Account] == A2.human());
|
||||
env.close();
|
||||
@@ -547,9 +543,8 @@ public:
|
||||
testOffersWhenFrozen(features);
|
||||
};
|
||||
using namespace test::jtx;
|
||||
auto const sa = supported_amendments();
|
||||
auto const sa = supported_amendments() - featureXahauGenesis;
|
||||
testAll(sa - featureFlowCross);
|
||||
testAll(sa - featureTouch);
|
||||
testAll(sa);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2102,10 +2102,9 @@ struct Remit_test : public beast::unit_test::suite
|
||||
std::string result;
|
||||
TER code;
|
||||
};
|
||||
// We test only rates that that can fit in a STI_UINT32.
|
||||
// Negative rates can't be serdes so there is no need to test them.
|
||||
std::array<TestRateData, 9> testCases = {{
|
||||
std::array<TestRateData, 10> testCases = {{
|
||||
{0.0, USD(100), "900", tesSUCCESS},
|
||||
{-1.0, USD(100), "900", temBAD_TRANSFER_RATE},
|
||||
{0.9, USD(100), "900", temBAD_TRANSFER_RATE},
|
||||
{1.0, USD(100), "900", tesSUCCESS},
|
||||
{1.1, USD(100), "890", tesSUCCESS},
|
||||
|
||||
140
src/test/app/SetHookV3_test.cpp
Normal file
140
src/test/app/SetHookV3_test.cpp
Normal file
@@ -0,0 +1,140 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012-2016 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
#include <ripple/app/hook/Enum.h>
|
||||
#include <ripple/app/ledger/LedgerMaster.h>
|
||||
#include <ripple/app/tx/impl/SetHook.h>
|
||||
#include <ripple/protocol/TxFlags.h>
|
||||
#include <ripple/protocol/jss.h>
|
||||
#include <test/app/SetHook_wasm.h>
|
||||
#include <test/jtx.h>
|
||||
#include <test/jtx/hook.h>
|
||||
#include <unordered_map>
|
||||
#include <iostream>
|
||||
#include <ripple/json/json_reader.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
namespace test {
|
||||
|
||||
class SetHookV3_test : public beast::unit_test::suite
|
||||
{
|
||||
private:
|
||||
// helper
|
||||
void static overrideFlag(Json::Value& jv)
|
||||
{
|
||||
jv[jss::Flags] = hsfOVERRIDE;
|
||||
}
|
||||
|
||||
public:
|
||||
// This is a large fee, large enough that we can set most small test hooks
|
||||
// without running into fee issues we only want to test fee code specifically in
|
||||
// fee unit tests, the rest of the time we want to ignore it.
|
||||
#define HSFEE fee(100'000'000)
|
||||
#define M(m) memo(m, "", "")
|
||||
std::string
|
||||
loadHook()
|
||||
{
|
||||
std::string name = "/Users/darkmatter/projects/ledger-works/xahaud/src/test/app/wasm/custom.wasm";
|
||||
if (!std::filesystem::exists(name)) {
|
||||
std::cout << "File does not exist: " << name << "\n";
|
||||
return "";
|
||||
}
|
||||
|
||||
std::ifstream hookFile(name, std::ios::binary);
|
||||
|
||||
if (!hookFile)
|
||||
{
|
||||
std::cout << "Failed to open file: " << name << "\n";
|
||||
return "";
|
||||
}
|
||||
|
||||
// Read the file into a vector
|
||||
std::vector<char> buffer((std::istreambuf_iterator<char>(hookFile)), std::istreambuf_iterator<char>());
|
||||
|
||||
// Check if the buffer is empty
|
||||
if (buffer.empty()) {
|
||||
std::cout << "File is empty or could not be read properly.\n";
|
||||
return "";
|
||||
}
|
||||
|
||||
return strHex(buffer);
|
||||
}
|
||||
|
||||
void
|
||||
testSimple(FeatureBitset features)
|
||||
{
|
||||
testcase("Test simple");
|
||||
|
||||
using namespace jtx;
|
||||
|
||||
// Env env{*this, features};
|
||||
Env env{*this, envconfig(), features, nullptr,
|
||||
beast::severities::kTrace
|
||||
};
|
||||
|
||||
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)));
|
||||
env.close();
|
||||
|
||||
std::string hook = loadHook();
|
||||
std::cout << "Hook: " << hook << "\n";
|
||||
|
||||
// install the hook on alice
|
||||
env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0),
|
||||
M("set simple"),
|
||||
HSFEE);
|
||||
env.close();
|
||||
|
||||
// // invoke the hook
|
||||
// Json::Value jv = invoke::invoke(alice);
|
||||
// Json::Value params{Json::arrayValue};
|
||||
// Json::Value pv;
|
||||
// Json::Value piv;
|
||||
// piv[jss::HookParameterName] = "736F6D6566756E63";
|
||||
// piv[jss::HookParameterValue] = "736F6D6566756E63";
|
||||
// pv[jss::HookParameter] = piv;
|
||||
// params[0u] = pv;
|
||||
// jv[jss::HookParameters] = params;
|
||||
env(invoke::invoke(alice), M("test simple"), fee(XRP(1)));
|
||||
}
|
||||
|
||||
void
|
||||
testWithFeatures(FeatureBitset features)
|
||||
{
|
||||
testSimple(features);
|
||||
}
|
||||
|
||||
void
|
||||
run() override
|
||||
{
|
||||
using namespace test::jtx;
|
||||
auto const sa = supported_amendments();
|
||||
testWithFeatures(sa);
|
||||
}
|
||||
};
|
||||
BEAST_DEFINE_TESTSUITE(SetHookV3, app, ripple);
|
||||
} // namespace test
|
||||
} // namespace ripple
|
||||
#undef M
|
||||
File diff suppressed because it is too large
Load Diff
10
src/test/app/contracts/base.c
Normal file
10
src/test/app/contracts/base.c
Normal file
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
#include "hookapi.h"
|
||||
|
||||
int64_t hook(uint32_t reserved) {
|
||||
TRACESTR("Base.c: Called.");
|
||||
_g(1,1);
|
||||
return accept(SBUF("base: Finished."), __LINE__);;
|
||||
}
|
||||
20
src/test/app/contracts/custom.c
Normal file
20
src/test/app/contracts/custom.c
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
#include "hookapi.h"
|
||||
// #define DEBUG 1
|
||||
// #define SBUF(str) (uint32_t)(str), sizeof(str)
|
||||
// #define TRACESTR(v) if (DEBUG) trace((uint32_t)(#v), (uint32_t)(sizeof(#v) - 1), (uint32_t)(v), sizeof(v), 0);
|
||||
// // hook developers should use this guard macro, simply GUARD(<maximum iterations>)
|
||||
// #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1)
|
||||
// #define GUARDM(maxiter, n) _g(( (1ULL << 31U) + (__LINE__ << 16) + n), (maxiter)+1)
|
||||
|
||||
// hooks-cli compile-c contracts/custom.c build
|
||||
|
||||
int64_t methodCreate(uint32_t reserved) {
|
||||
TRACESTR("somefunc.c: Called.");
|
||||
for (int i = 0; GUARD(10), i < 10; i++) {
|
||||
TRACESTR("somefunc.c: Iterating.");
|
||||
}
|
||||
return accept(SBUF("somefunc.c: Finished."), __LINE__);
|
||||
}
|
||||
@@ -1138,209 +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;
|
||||
|
||||
bool const withTouch = env.current()->rules().enabled(featureTouch);
|
||||
{
|
||||
// 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 withTouch ? false : true;
|
||||
}));
|
||||
}
|
||||
|
||||
// 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
|
||||
{
|
||||
@@ -1358,8 +1155,6 @@ public:
|
||||
testSubErrors(false);
|
||||
testSubByUrl();
|
||||
testHistoryTxStream();
|
||||
testAccount(all);
|
||||
testAccount(all - featureTouch);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user