mirror of
https://github.com/Xahau/xahaud.git
synced 2025-11-19 10:05:48 +00:00
Touch Amendment (#294)
This commit is contained in:
@@ -755,6 +755,7 @@ if (tests)
|
|||||||
src/test/app/Taker_test.cpp
|
src/test/app/Taker_test.cpp
|
||||||
src/test/app/TheoreticalQuality_test.cpp
|
src/test/app/TheoreticalQuality_test.cpp
|
||||||
src/test/app/Ticket_test.cpp
|
src/test/app/Ticket_test.cpp
|
||||||
|
src/test/app/Touch_test.cpp
|
||||||
src/test/app/Transaction_ordering_test.cpp
|
src/test/app/Transaction_ordering_test.cpp
|
||||||
src/test/app/TrustAndBalance_test.cpp
|
src/test/app/TrustAndBalance_test.cpp
|
||||||
src/test/app/TxQ_test.cpp
|
src/test/app/TxQ_test.cpp
|
||||||
|
|||||||
@@ -1079,6 +1079,24 @@ 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
|
static void
|
||||||
removeUnfundedOffers(
|
removeUnfundedOffers(
|
||||||
ApplyView& view,
|
ApplyView& view,
|
||||||
@@ -1519,6 +1537,8 @@ Transactor::doTSH(
|
|||||||
if ((!canRollback && strong) || (canRollback && !strong))
|
if ((!canRollback && strong) || (canRollback && !strong))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
touchAccount(view, tshAccountID);
|
||||||
|
|
||||||
auto klTshHook = keylet::hook(tshAccountID);
|
auto klTshHook = keylet::hook(tshAccountID);
|
||||||
|
|
||||||
auto tshHook = view.read(klTshHook);
|
auto tshHook = view.read(klTshHook);
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ namespace detail {
|
|||||||
// Feature.cpp. Because it's only used to reserve storage, and determine how
|
// 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
|
// 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.
|
// the actual number of amendments. A LogicError on startup will verify this.
|
||||||
static constexpr std::size_t numFeatures = 77;
|
static constexpr std::size_t numFeatures = 78;
|
||||||
|
|
||||||
/** Amendments that this server supports and the default voting behavior.
|
/** Amendments that this server supports and the default voting behavior.
|
||||||
Whether they are enabled depends on the Rules defined in the validated
|
Whether they are enabled depends on the Rules defined in the validated
|
||||||
@@ -362,6 +362,7 @@ extern uint256 const fix240819;
|
|||||||
extern uint256 const fixPageCap;
|
extern uint256 const fixPageCap;
|
||||||
extern uint256 const fix240911;
|
extern uint256 const fix240911;
|
||||||
extern uint256 const fixFloatDivide;
|
extern uint256 const fixFloatDivide;
|
||||||
|
extern uint256 const featureTouch;
|
||||||
extern uint256 const fixReduceImport;
|
extern uint256 const fixReduceImport;
|
||||||
extern uint256 const fixXahauV3;
|
extern uint256 const fixXahauV3;
|
||||||
extern uint256 const fix20250131;
|
extern uint256 const fix20250131;
|
||||||
|
|||||||
@@ -433,6 +433,7 @@ extern SF_UINT64 const sfReferenceCount;
|
|||||||
extern SF_UINT64 const sfRewardAccumulator;
|
extern SF_UINT64 const sfRewardAccumulator;
|
||||||
extern SF_UINT64 const sfAccountCount;
|
extern SF_UINT64 const sfAccountCount;
|
||||||
extern SF_UINT64 const sfAccountIndex;
|
extern SF_UINT64 const sfAccountIndex;
|
||||||
|
extern SF_UINT64 const sfTouchCount;
|
||||||
|
|
||||||
// 128-bit
|
// 128-bit
|
||||||
extern SF_UINT128 const sfEmailHash;
|
extern SF_UINT128 const sfEmailHash;
|
||||||
|
|||||||
@@ -468,6 +468,7 @@ REGISTER_FIX (fix240819, Supported::yes, VoteBehavior::De
|
|||||||
REGISTER_FIX (fixPageCap, Supported::yes, VoteBehavior::DefaultYes);
|
REGISTER_FIX (fixPageCap, Supported::yes, VoteBehavior::DefaultYes);
|
||||||
REGISTER_FIX (fix240911, Supported::yes, VoteBehavior::DefaultYes);
|
REGISTER_FIX (fix240911, Supported::yes, VoteBehavior::DefaultYes);
|
||||||
REGISTER_FIX (fixFloatDivide, 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 (fixReduceImport, Supported::yes, VoteBehavior::DefaultYes);
|
||||||
REGISTER_FIX (fixXahauV3, Supported::yes, VoteBehavior::DefaultYes);
|
REGISTER_FIX (fixXahauV3, Supported::yes, VoteBehavior::DefaultYes);
|
||||||
REGISTER_FIX (fix20250131, Supported::yes, VoteBehavior::DefaultYes);
|
REGISTER_FIX (fix20250131, Supported::yes, VoteBehavior::DefaultYes);
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ LedgerFormats::LedgerFormats()
|
|||||||
{sfGovernanceFlags, soeOPTIONAL},
|
{sfGovernanceFlags, soeOPTIONAL},
|
||||||
{sfGovernanceMarks, soeOPTIONAL},
|
{sfGovernanceMarks, soeOPTIONAL},
|
||||||
{sfAccountIndex, soeOPTIONAL},
|
{sfAccountIndex, soeOPTIONAL},
|
||||||
|
{sfTouchCount, soeOPTIONAL},
|
||||||
},
|
},
|
||||||
commonFields);
|
commonFields);
|
||||||
|
|
||||||
|
|||||||
@@ -183,6 +183,7 @@ CONSTRUCT_TYPED_SFIELD(sfEmitBurden, "EmitBurden", UINT64,
|
|||||||
CONSTRUCT_TYPED_SFIELD(sfHookInstructionCount, "HookInstructionCount", UINT64, 17);
|
CONSTRUCT_TYPED_SFIELD(sfHookInstructionCount, "HookInstructionCount", UINT64, 17);
|
||||||
CONSTRUCT_TYPED_SFIELD(sfHookReturnCode, "HookReturnCode", UINT64, 18);
|
CONSTRUCT_TYPED_SFIELD(sfHookReturnCode, "HookReturnCode", UINT64, 18);
|
||||||
CONSTRUCT_TYPED_SFIELD(sfReferenceCount, "ReferenceCount", UINT64, 19);
|
CONSTRUCT_TYPED_SFIELD(sfReferenceCount, "ReferenceCount", UINT64, 19);
|
||||||
|
CONSTRUCT_TYPED_SFIELD(sfTouchCount, "TouchCount", UINT64, 97);
|
||||||
CONSTRUCT_TYPED_SFIELD(sfAccountIndex, "AccountIndex", UINT64, 98);
|
CONSTRUCT_TYPED_SFIELD(sfAccountIndex, "AccountIndex", UINT64, 98);
|
||||||
CONSTRUCT_TYPED_SFIELD(sfAccountCount, "AccountCount", UINT64, 99);
|
CONSTRUCT_TYPED_SFIELD(sfAccountCount, "AccountCount", UINT64, 99);
|
||||||
CONSTRUCT_TYPED_SFIELD(sfRewardAccumulator, "RewardAccumulator", UINT64, 100);
|
CONSTRUCT_TYPED_SFIELD(sfRewardAccumulator, "RewardAccumulator", UINT64, 100);
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ class Discrepancy_test : public beast::unit_test::suite
|
|||||||
using namespace test::jtx;
|
using namespace test::jtx;
|
||||||
Env env{*this, features};
|
Env env{*this, features};
|
||||||
|
|
||||||
|
bool const withTouch = env.current()->rules().enabled(featureTouch);
|
||||||
|
|
||||||
Account A1{"A1"};
|
Account A1{"A1"};
|
||||||
Account A2{"A2"};
|
Account A2{"A2"};
|
||||||
Account A3{"A3"};
|
Account A3{"A3"};
|
||||||
@@ -107,7 +109,8 @@ class Discrepancy_test : public beast::unit_test::suite
|
|||||||
auto meta = jrr[jss::meta];
|
auto meta = jrr[jss::meta];
|
||||||
uint64_t sumPrev{0};
|
uint64_t sumPrev{0};
|
||||||
uint64_t sumFinal{0};
|
uint64_t sumFinal{0};
|
||||||
BEAST_EXPECT(meta[sfAffectedNodes.fieldName].size() == 9);
|
BEAST_EXPECT(
|
||||||
|
meta[sfAffectedNodes.fieldName].size() == withTouch ? 11 : 10);
|
||||||
for (auto const& an : meta[sfAffectedNodes.fieldName])
|
for (auto const& an : meta[sfAffectedNodes.fieldName])
|
||||||
{
|
{
|
||||||
Json::Value node;
|
Json::Value node;
|
||||||
@@ -127,12 +130,17 @@ class Discrepancy_test : public beast::unit_test::suite
|
|||||||
Json::Value finalFields = node.isMember(sfFinalFields.fieldName)
|
Json::Value finalFields = node.isMember(sfFinalFields.fieldName)
|
||||||
? node[sfFinalFields.fieldName]
|
? node[sfFinalFields.fieldName]
|
||||||
: node[sfNewFields.fieldName];
|
: node[sfNewFields.fieldName];
|
||||||
if (prevFields)
|
|
||||||
sumPrev += beast::lexicalCastThrow<std::uint64_t>(
|
// withTouch: "Touched" account does not update Balance
|
||||||
prevFields[sfBalance.fieldName].asString());
|
if (prevFields.isMember(sfBalance.fieldName))
|
||||||
if (finalFields)
|
{
|
||||||
sumFinal += beast::lexicalCastThrow<std::uint64_t>(
|
if (prevFields)
|
||||||
finalFields[sfBalance.fieldName].asString());
|
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
|
// the difference in balances (final and prev) should be the
|
||||||
@@ -147,6 +155,7 @@ public:
|
|||||||
using namespace test::jtx;
|
using namespace test::jtx;
|
||||||
auto const sa = supported_amendments();
|
auto const sa = supported_amendments();
|
||||||
testXRPDiscrepancy(sa - featureFlowCross);
|
testXRPDiscrepancy(sa - featureFlowCross);
|
||||||
|
testXRPDiscrepancy(sa - featureTouch);
|
||||||
testXRPDiscrepancy(sa);
|
testXRPDiscrepancy(sa);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ class Freeze_test : public beast::unit_test::suite
|
|||||||
|
|
||||||
using namespace test::jtx;
|
using namespace test::jtx;
|
||||||
Env env(*this, features);
|
Env env(*this, features);
|
||||||
|
bool const withTouch = env.current()->rules().enabled(featureTouch);
|
||||||
|
|
||||||
Account G1{"G1"};
|
Account G1{"G1"};
|
||||||
Account alice{"alice"};
|
Account alice{"alice"};
|
||||||
@@ -113,7 +114,7 @@ class Freeze_test : public beast::unit_test::suite
|
|||||||
env(trust(G1, bob["USD"](0), tfSetFreeze));
|
env(trust(G1, bob["USD"](0), tfSetFreeze));
|
||||||
auto affected = env.meta()->getJson(
|
auto affected = env.meta()->getJson(
|
||||||
JsonOptions::none)[sfAffectedNodes.fieldName];
|
JsonOptions::none)[sfAffectedNodes.fieldName];
|
||||||
if (!BEAST_EXPECT(checkArraySize(affected, 2u)))
|
if (!BEAST_EXPECT(checkArraySize(affected, withTouch ? 3u : 2u)))
|
||||||
return;
|
return;
|
||||||
auto ff =
|
auto ff =
|
||||||
affected[1u][sfModifiedNode.fieldName][sfFinalFields.fieldName];
|
affected[1u][sfModifiedNode.fieldName][sfFinalFields.fieldName];
|
||||||
@@ -131,10 +132,10 @@ class Freeze_test : public beast::unit_test::suite
|
|||||||
env(offer(bob, G1["USD"](5), XRP(25)));
|
env(offer(bob, G1["USD"](5), XRP(25)));
|
||||||
auto affected = env.meta()->getJson(
|
auto affected = env.meta()->getJson(
|
||||||
JsonOptions::none)[sfAffectedNodes.fieldName];
|
JsonOptions::none)[sfAffectedNodes.fieldName];
|
||||||
if (!BEAST_EXPECT(checkArraySize(affected, 5u)))
|
if (!BEAST_EXPECT(checkArraySize(affected, withTouch ? 6u : 5u)))
|
||||||
return;
|
return;
|
||||||
auto ff =
|
auto ff = affected[withTouch ? 4u : 3u][sfModifiedNode.fieldName]
|
||||||
affected[3u][sfModifiedNode.fieldName][sfFinalFields.fieldName];
|
[sfFinalFields.fieldName];
|
||||||
BEAST_EXPECT(
|
BEAST_EXPECT(
|
||||||
ff[sfHighLimit.fieldName] ==
|
ff[sfHighLimit.fieldName] ==
|
||||||
bob["USD"](100).value().getJson(JsonOptions::none));
|
bob["USD"](100).value().getJson(JsonOptions::none));
|
||||||
@@ -199,7 +200,7 @@ class Freeze_test : public beast::unit_test::suite
|
|||||||
env(trust(G1, bob["USD"](0), tfClearFreeze));
|
env(trust(G1, bob["USD"](0), tfClearFreeze));
|
||||||
auto affected = env.meta()->getJson(
|
auto affected = env.meta()->getJson(
|
||||||
JsonOptions::none)[sfAffectedNodes.fieldName];
|
JsonOptions::none)[sfAffectedNodes.fieldName];
|
||||||
if (!BEAST_EXPECT(checkArraySize(affected, 2u)))
|
if (!BEAST_EXPECT(checkArraySize(affected, withTouch ? 3u : 2u)))
|
||||||
return;
|
return;
|
||||||
auto ff =
|
auto ff =
|
||||||
affected[1u][sfModifiedNode.fieldName][sfFinalFields.fieldName];
|
affected[1u][sfModifiedNode.fieldName][sfFinalFields.fieldName];
|
||||||
@@ -377,6 +378,7 @@ class Freeze_test : public beast::unit_test::suite
|
|||||||
|
|
||||||
using namespace test::jtx;
|
using namespace test::jtx;
|
||||||
Env env(*this, features);
|
Env env(*this, features);
|
||||||
|
bool const withTouch = env.current()->rules().enabled(featureTouch);
|
||||||
|
|
||||||
Account G1{"G1"};
|
Account G1{"G1"};
|
||||||
Account A1{"A1"};
|
Account A1{"A1"};
|
||||||
@@ -417,7 +419,7 @@ class Freeze_test : public beast::unit_test::suite
|
|||||||
env(trust(G1, A1["USD"](0), tfSetFreeze));
|
env(trust(G1, A1["USD"](0), tfSetFreeze));
|
||||||
auto affected =
|
auto affected =
|
||||||
env.meta()->getJson(JsonOptions::none)[sfAffectedNodes.fieldName];
|
env.meta()->getJson(JsonOptions::none)[sfAffectedNodes.fieldName];
|
||||||
if (!BEAST_EXPECT(checkArraySize(affected, 1u)))
|
if (!BEAST_EXPECT(checkArraySize(affected, withTouch ? 2u : 1u)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto let =
|
auto let =
|
||||||
@@ -432,6 +434,7 @@ class Freeze_test : public beast::unit_test::suite
|
|||||||
|
|
||||||
using namespace test::jtx;
|
using namespace test::jtx;
|
||||||
Env env(*this, features);
|
Env env(*this, features);
|
||||||
|
bool const withTouch = env.current()->rules().enabled(featureTouch);
|
||||||
|
|
||||||
Account G1{"G1"};
|
Account G1{"G1"};
|
||||||
Account A2{"A2"};
|
Account A2{"A2"};
|
||||||
@@ -475,7 +478,7 @@ class Freeze_test : public beast::unit_test::suite
|
|||||||
env(trust(G1, A3["USD"](0), tfSetFreeze));
|
env(trust(G1, A3["USD"](0), tfSetFreeze));
|
||||||
auto affected =
|
auto affected =
|
||||||
env.meta()->getJson(JsonOptions::none)[sfAffectedNodes.fieldName];
|
env.meta()->getJson(JsonOptions::none)[sfAffectedNodes.fieldName];
|
||||||
if (!BEAST_EXPECT(checkArraySize(affected, 2u)))
|
if (!BEAST_EXPECT(checkArraySize(affected, withTouch ? 3u : 2u)))
|
||||||
return;
|
return;
|
||||||
auto ff =
|
auto ff =
|
||||||
affected[1u][sfModifiedNode.fieldName][sfFinalFields.fieldName];
|
affected[1u][sfModifiedNode.fieldName][sfFinalFields.fieldName];
|
||||||
@@ -505,9 +508,10 @@ class Freeze_test : public beast::unit_test::suite
|
|||||||
env(trust(G1, A4["USD"](0), tfSetFreeze));
|
env(trust(G1, A4["USD"](0), tfSetFreeze));
|
||||||
affected =
|
affected =
|
||||||
env.meta()->getJson(JsonOptions::none)[sfAffectedNodes.fieldName];
|
env.meta()->getJson(JsonOptions::none)[sfAffectedNodes.fieldName];
|
||||||
if (!BEAST_EXPECT(checkArraySize(affected, 2u)))
|
if (!BEAST_EXPECT(checkArraySize(affected, withTouch ? 3u : 2u)))
|
||||||
return;
|
return;
|
||||||
ff = affected[0u][sfModifiedNode.fieldName][sfFinalFields.fieldName];
|
ff = affected[withTouch ? 1u : 0u][sfModifiedNode.fieldName]
|
||||||
|
[sfFinalFields.fieldName];
|
||||||
BEAST_EXPECT(
|
BEAST_EXPECT(
|
||||||
ff[sfLowLimit.fieldName] ==
|
ff[sfLowLimit.fieldName] ==
|
||||||
G1["USD"](0).value().getJson(JsonOptions::none));
|
G1["USD"](0).value().getJson(JsonOptions::none));
|
||||||
@@ -521,7 +525,7 @@ class Freeze_test : public beast::unit_test::suite
|
|||||||
env.meta()->getJson(JsonOptions::none)[sfAffectedNodes.fieldName];
|
env.meta()->getJson(JsonOptions::none)[sfAffectedNodes.fieldName];
|
||||||
if (!BEAST_EXPECT(checkArraySize(affected, 8u)))
|
if (!BEAST_EXPECT(checkArraySize(affected, 8u)))
|
||||||
return;
|
return;
|
||||||
auto created = affected[0u][sfCreatedNode.fieldName];
|
auto created = affected[5u][sfCreatedNode.fieldName];
|
||||||
BEAST_EXPECT(
|
BEAST_EXPECT(
|
||||||
created[sfNewFields.fieldName][jss::Account] == A2.human());
|
created[sfNewFields.fieldName][jss::Account] == A2.human());
|
||||||
env.close();
|
env.close();
|
||||||
@@ -543,8 +547,9 @@ public:
|
|||||||
testOffersWhenFrozen(features);
|
testOffersWhenFrozen(features);
|
||||||
};
|
};
|
||||||
using namespace test::jtx;
|
using namespace test::jtx;
|
||||||
auto const sa = supported_amendments() - featureXahauGenesis;
|
auto const sa = supported_amendments();
|
||||||
testAll(sa - featureFlowCross);
|
testAll(sa - featureFlowCross);
|
||||||
|
testAll(sa - featureTouch);
|
||||||
testAll(sa);
|
testAll(sa);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
1411
src/test/app/Touch_test.cpp
Normal file
1411
src/test/app/Touch_test.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1138,6 +1138,209 @@ 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
|
void
|
||||||
run() override
|
run() override
|
||||||
{
|
{
|
||||||
@@ -1155,6 +1358,8 @@ public:
|
|||||||
testSubErrors(false);
|
testSubErrors(false);
|
||||||
testSubByUrl();
|
testSubByUrl();
|
||||||
testHistoryTxStream();
|
testHistoryTxStream();
|
||||||
|
testAccount(all);
|
||||||
|
testAccount(all - featureTouch);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user