22#include <xrpld/app/consensus/RCLValidations.h>
23#include <xrpld/app/ledger/Ledger.h>
24#include <xrpld/app/misc/NegativeUNLVote.h>
25#include <xrpld/app/misc/ValidatorList.h>
26#include <xrpld/app/tx/apply.h>
28#include <xrpl/beast/unit_test.h>
29#include <xrpl/ledger/View.h>
87 hash_map<PublicKey, std::uint32_t> nUnlLedgerSeq);
228 testcase(
"Create UNLModify Tx and apply to ledgers");
238 BEAST_EXPECT(l->rules().enabled(featureNegativeUNL));
249 auto txDisable_0 =
createTx(
true, l->seq(), publicKeys[0]);
250 auto txReEnable_1 =
createTx(
false, l->seq(), publicKeys[1]);
262 for (
auto i = 0; i < 256 - 2; ++i)
267 BEAST_EXPECT(l->isFlagLedger());
268 l->updateNegativeUNL();
270 auto txDisable_0 =
createTx(
true, l->seq(), publicKeys[0]);
271 auto txDisable_1 =
createTx(
true, l->seq(), publicKeys[1]);
272 auto txReEnable_2 =
createTx(
false, l->seq(), publicKeys[2]);
282 BEAST_EXPECT(good_size);
285 BEAST_EXPECT(l->validatorToDisable() == publicKeys[0]);
287 uint256 txID = txDisable_0.getTransactionID();
288 BEAST_EXPECT(l->txExists(txID));
294 for (
auto i = 0; i < 256; ++i)
297 BEAST_EXPECT(good_size);
299 BEAST_EXPECT(l->validatorToDisable() == publicKeys[0]);
303 BEAST_EXPECT(l->isFlagLedger());
304 l->updateNegativeUNL();
309 BEAST_EXPECT(good_size);
312 BEAST_EXPECT(*(l->negativeUNL().begin()) == publicKeys[0]);
313 nUnlLedgerSeq.
emplace(publicKeys[0], l->seq());
316 auto txDisable_0 =
createTx(
true, l->seq(), publicKeys[0]);
317 auto txDisable_1 =
createTx(
true, l->seq(), publicKeys[1]);
318 auto txReEnable_0 =
createTx(
false, l->seq(), publicKeys[0]);
319 auto txReEnable_1 =
createTx(
false, l->seq(), publicKeys[1]);
320 auto txReEnable_2 =
createTx(
false, l->seq(), publicKeys[2]);
330 BEAST_EXPECT(good_size);
333 BEAST_EXPECT(l->negativeUNL().count(publicKeys[0]));
334 BEAST_EXPECT(l->validatorToDisable() == publicKeys[1]);
335 BEAST_EXPECT(l->validatorToReEnable() == publicKeys[0]);
343 for (
auto i = 0; i < 256; ++i)
346 BEAST_EXPECT(good_size);
349 BEAST_EXPECT(l->negativeUNL().count(publicKeys[0]));
350 BEAST_EXPECT(l->validatorToDisable() == publicKeys[1]);
351 BEAST_EXPECT(l->validatorToReEnable() == publicKeys[0]);
356 BEAST_EXPECT(l->isFlagLedger());
357 l->updateNegativeUNL();
362 BEAST_EXPECT(good_size);
365 BEAST_EXPECT(l->negativeUNL().count(publicKeys[1]));
368 auto txDisable_0 =
createTx(
true, l->seq(), publicKeys[0]);
374 BEAST_EXPECT(good_size);
377 BEAST_EXPECT(l->negativeUNL().count(publicKeys[1]));
378 BEAST_EXPECT(l->validatorToDisable() == publicKeys[0]);
379 nUnlLedgerSeq.
emplace(publicKeys[1], l->seq());
380 nUnlLedgerSeq.
erase(publicKeys[0]);
387 for (
auto i = 0; i < 256; ++i)
390 BEAST_EXPECT(good_size);
393 BEAST_EXPECT(l->negativeUNL().count(publicKeys[1]));
394 BEAST_EXPECT(l->validatorToDisable() == publicKeys[0]);
399 BEAST_EXPECT(l->isFlagLedger());
400 l->updateNegativeUNL();
405 BEAST_EXPECT(good_size);
408 BEAST_EXPECT(l->negativeUNL().count(publicKeys[0]));
409 BEAST_EXPECT(l->negativeUNL().count(publicKeys[1]));
410 nUnlLedgerSeq.
emplace(publicKeys[0], l->seq());
414 auto txDisable_0 =
createTx(
true, l->seq(), publicKeys[0]);
415 auto txReEnable_0 =
createTx(
false, l->seq(), publicKeys[0]);
416 auto txReEnable_1 =
createTx(
false, l->seq(), publicKeys[1]);
424 BEAST_EXPECT(good_size);
427 BEAST_EXPECT(l->negativeUNL().count(publicKeys[0]));
428 BEAST_EXPECT(l->negativeUNL().count(publicKeys[1]));
429 BEAST_EXPECT(l->validatorToReEnable() == publicKeys[0]);
436 for (
auto i = 0; i < 256; ++i)
439 BEAST_EXPECT(good_size);
442 BEAST_EXPECT(l->negativeUNL().count(publicKeys[0]));
443 BEAST_EXPECT(l->negativeUNL().count(publicKeys[1]));
444 BEAST_EXPECT(l->validatorToReEnable() == publicKeys[0]);
449 BEAST_EXPECT(l->isFlagLedger());
450 l->updateNegativeUNL();
455 BEAST_EXPECT(good_size);
458 BEAST_EXPECT(l->negativeUNL().count(publicKeys[1]));
459 nUnlLedgerSeq.
erase(publicKeys[0]);
463 auto txReEnable_1 =
createTx(
false, l->seq(), publicKeys[1]);
469 BEAST_EXPECT(good_size);
472 BEAST_EXPECT(l->negativeUNL().count(publicKeys[1]));
473 BEAST_EXPECT(l->validatorToReEnable() == publicKeys[1]);
480 for (
auto i = 0; i < 256; ++i)
483 BEAST_EXPECT(good_size);
486 BEAST_EXPECT(l->negativeUNL().count(publicKeys[1]));
487 BEAST_EXPECT(l->validatorToReEnable() == publicKeys[1]);
492 BEAST_EXPECT(l->isFlagLedger());
493 l->updateNegativeUNL();
501 for (
auto i = 0; i < 256; ++i)
507 BEAST_EXPECT(l->isFlagLedger());
508 l->updateNegativeUNL();
527 testcase(
"No negative UNL amendment");
537 BEAST_EXPECT(!l->rules().enabled(featureNegativeUNL));
540 for (
auto i = 0; i < 256 - 1; ++i)
545 BEAST_EXPECT(l->seq() == 256);
546 auto txDisable_0 =
createTx(
true, l->seq(), publicKeys[0]);
632 if (l->isFlagLedger())
634 l->updateNegativeUNL();
683 v.setFieldH256(sfLedgerHash, ledger->info().hash);
684 v.setFieldU32(sfLedgerSequence, ledger->seq());
685 v.setFlag(vfFullValidation);
696 template <
class NeedVal
idation>
748template <
typename PreVote = decltype(defaultPreVote)>
762 return countTx(txSet) == expect;
787 BEAST_EXPECT(
countTx(txSet) == 0);
789 BEAST_EXPECT(
countTx(txSet) == 1);
791 BEAST_EXPECT(
countTx(txSet) == 2);
811 BEAST_EXPECT(vote.
choose(pad_0, candidates) == n_1);
812 BEAST_EXPECT(vote.
choose(pad_f, candidates) == n_1);
813 candidates.emplace_back(2);
814 BEAST_EXPECT(vote.
choose(pad_0, candidates) == n_1);
815 BEAST_EXPECT(vote.
choose(pad_f, candidates) == n_2);
816 candidates.emplace_back(3);
817 BEAST_EXPECT(vote.
choose(pad_0, candidates) == n_1);
818 BEAST_EXPECT(vote.
choose(pad_f, candidates) == n_3);
892 BEAST_EXPECT(wrongChainSuccess);
913 for (
auto& l : wrongChain)
929 BEAST_EXPECT(scoreTable);
932 for (
auto const& [n, score] : *scoreTable)
935 BEAST_EXPECT(score == 256);
937 BEAST_EXPECT(score == 0);
965 BEAST_EXPECT(scoreTable);
968 for (
auto const& [_, score] : *scoreTable)
971 BEAST_EXPECT(score == 256);
999 auto [disableCandidates, reEnableCandidates] =
1001 bool rightDisable = disableCandidates.size() == numDisable;
1002 bool rightReEnable = reEnableCandidates.size() == numReEnable;
1003 return rightDisable && rightReEnable;
1042 vote, history.
UNLNodeIDSet, negUnl_012, goodScoreTable, 0, 3));
1050 vote, history.
UNLNodeIDSet, negUnl_012, scoreTable, 35 - 3, 0));
1058 vote, history.
UNLNodeIDSet, negUnl_012, scoreTable, 0, 0));
1063 auto scoreTable = goodScoreTable;
1064 scoreTable[*negUnl_012.
begin()] =
1067 vote, history.
UNLNodeIDSet, negUnl_012, scoreTable, 0, 2));
1072 auto scoreTable = goodScoreTable;
1078 vote, history.
UNLNodeIDSet, negUnl_012, scoreTable, 2, 3));
1088 vote, UNL_temp, negUnl_012, goodScoreTable, 0, 3));
1093 auto scoreTable = goodScoreTable;
1102 vote, UNL_temp, negUnl_012, scoreTable, 0, 2));
1116 auto scoreTable = goodScoreTable;
1122 negUnl_temp.
insert(new_1);
1123 negUnl_temp.
insert(new_2);
1125 vote, UNL_temp, negUnl_temp, scoreTable, 0, 3 + 2));
1129 auto scoreTable = goodScoreTable;
1130 scoreTable[new_1] = 0;
1131 scoreTable[new_2] = 0;
1133 vote, UNL_temp, negUnl_012, scoreTable, 0, 3));
1139 auto scoreTable = goodScoreTable;
1140 scoreTable[new_1] = 0;
1141 scoreTable[new_2] = 0;
1143 vote, UNL_temp, negUnl_012, scoreTable, 2, 3));
1151 testcase(
"Find All Candidates Combination");
1187 auto fillScoreTable =
1196 for (
auto const& k : keys)
1199 unl.emplace(nodeIDs.
back());
1200 scoreTable[nodeIDs.
back()] = score;
1203 negUnl.insert(nodeIDs[i]);
1206 for (
auto us : unlSizes)
1208 for (
auto np : nUnlPercent)
1210 for (
auto score : scores)
1216 us, us * np / 100, score, unl, negUnl, scoreTable);
1217 BEAST_EXPECT(unl.
size() == us);
1218 BEAST_EXPECT(negUnl.
size() == us * np / 100);
1219 BEAST_EXPECT(scoreTable.
size() == us);
1228 toDisable_expect = us;
1236 toReEnable_expect = us * np / 100;
1244 toReEnable_expect = us;
1253 toReEnable_expect));
1260 auto fillScoreTable =
1269 for (
auto const& k : keys)
1272 unl.emplace(nodeIDs.
back());
1276 for (
auto score : scores)
1278 scoreTable[nodeIDs[nIdx++]] = score;
1279 scoreTable[nodeIDs[nIdx++]] = score;
1281 for (; nIdx < unl_size;)
1283 scoreTable[nodeIDs[nIdx++]] = scores.
back();
1286 if (nUnl_percent == 100)
1290 else if (nUnl_percent == 50)
1293 negUnl.insert(nodeIDs[i]);
1297 for (
auto us : unlSizes)
1299 for (
auto np : nUnlPercent)
1305 fillScoreTable(us, np, unl, negUnl, scoreTable);
1306 BEAST_EXPECT(unl.
size() == us);
1307 BEAST_EXPECT(negUnl.
size() == us * np / 100);
1308 BEAST_EXPECT(scoreTable.
size() == us);
1314 toDisable_expect = 4;
1318 toReEnable_expect = negUnl.
size() - 6;
1322 toReEnable_expect = negUnl.
size() - 12;
1330 toReEnable_expect));
1418 testcase(
"Build Score Table Combination");
1427 {{{0, 0, 0}}, {{50, 50, 50}}, {{100, 100, 100}}, {{0, 50, 100}}}};
1429 for (
auto unlSize : unlSizes)
1434 *
this, {unlSize, 0,
false,
false, 256 + 2}};
1451 scorePattern[sp][k] == 50 && l->seq() % 2 == 0;
1452 bool add_100 = scorePattern[sp][k] == 100;
1453 bool add_me = history.
UNLNodeIDs[idx] == myId;
1454 return add_50 || add_100 || add_me;
1462 BEAST_EXPECT(scoreTable);
1469 return score == 256;
1470 if (scorePattern[sp][k] == 0)
1472 if (scorePattern[sp][k] == 50)
1473 return score == 256 / 2;
1474 if (scorePattern[sp][k] == 100)
1475 return score == 256;
1481 BEAST_EXPECT(checkScores(
1486 BEAST_EXPECT(checkScores(
1489 for (; i < unlSize; ++i)
1491 BEAST_EXPECT(checkScores(
1721 history.UNLKeySet.erase(history.UNLKeys[0]);
1722 history.UNLKeySet.erase(history.UNLKeys[1]);
1758 randomKeyPair(KeyType::ed25519).first;
1760 randomKeyPair(KeyType::ed25519).first;
1761 history.UNLKeySet.insert(extra_key_1);
1762 history.UNLKeySet.insert(extra_key_2);
1763 hash_set<NodeID> nowTrusted;
1764 nowTrusted.insert(calcNodeID(extra_key_1));
1765 nowTrusted.insert(calcNodeID(extra_key_2));
1767 history.lastLedger()->seq(), nowTrusted);
1794 randomKeyPair(KeyType::ed25519).first;
1796 randomKeyPair(KeyType::ed25519).first;
1797 history.UNLKeySet.insert(extra_key_1);
1798 history.UNLKeySet.insert(extra_key_2);
1799 hash_set<NodeID> nowTrusted;
1800 nowTrusted.insert(calcNodeID(extra_key_1));
1801 nowTrusted.insert(calcNodeID(extra_key_2));
1802 vote.newValidators(256, nowTrusted);
1835 v.setFieldH256(sfLedgerHash, l->info().hash);
1836 v.setFieldU32(sfLedgerSequence, l->seq());
1837 v.setFlag(vfFullValidation);
1848 for (
int i = 0; i < numNodes; ++i)
1856 nUnlKeys.
insert(keyPair.first);
1862 auto& local = *nUnlKeys.
begin();
1864 validators.load(local, cfgKeys, cfgPublishers);
1865 validators.updateTrusted(
1871 BEAST_EXPECT(validators.getTrustedMasterKeys().size() == numNodes);
1872 validators.setNegativeUNL(nUnlKeys);
1873 BEAST_EXPECT(validators.getNegativeUNL().size() == negUnlSize);
1876 BEAST_EXPECT(vals.
size() == numNodes);
1877 vals = validators.negativeUNLFilter(std::move(vals));
1878 BEAST_EXPECT(vals.
size() == numNodes - negUnlSize);
1888BEAST_DEFINE_TESTSUITE(NegativeUNL, consensus,
ripple);
1889BEAST_DEFINE_TESTSUITE(NegativeUNLNoAmendment, consensus,
ripple);
1891BEAST_DEFINE_TESTSUITE(NegativeUNLVoteInternal, consensus,
ripple);
1892BEAST_DEFINE_TESTSUITE_MANUAL(NegativeUNLVoteScoreTable, consensus,
ripple);
1893BEAST_DEFINE_TESTSUITE_PRIO(NegativeUNLVoteGoodScore, consensus,
ripple, 1);
1894BEAST_DEFINE_TESTSUITE(NegativeUNLVoteOffline, consensus,
ripple);
1895BEAST_DEFINE_TESTSUITE(NegativeUNLVoteMaxListed, consensus,
ripple);
1896BEAST_DEFINE_TESTSUITE_PRIO(
1897 NegativeUNLVoteRetiredValidator,
1901BEAST_DEFINE_TESTSUITE(NegativeUNLVoteNewValidator, consensus,
ripple);
1902BEAST_DEFINE_TESTSUITE(NegativeUNLVoteFilterValidations, consensus,
ripple);
1914 bool sameSize = l->negativeUNL().size() == size;
1915 bool sameToDisable =
1916 (l->validatorToDisable() !=
std::nullopt) == hasToDisable;
1917 bool sameToReEnable =
1918 (l->validatorToReEnable() !=
std::nullopt) == hasToReEnable;
1920 return sameSize && sameToDisable && sameToReEnable;
1942 if (!sle->isFieldPresent(sfDisabledValidators))
1945 auto const& nUnlData = sle->getFieldArray(sfDisabledValidators);
1946 if (nUnlData.size() != nUnlLedgerSeq.
size())
1949 for (
auto const& n : nUnlData)
1951 if (!n.isFieldPresent(sfFirstLedgerSequence) ||
1952 !n.isFieldPresent(sfPublicKey))
1955 auto seq = n.getFieldU32(sfFirstLedgerSequence);
1956 auto d = n.getFieldVL(sfPublicKey);
1961 auto it = nUnlLedgerSeq.
find(pk);
1962 if (it == nUnlLedgerSeq.
end())
1964 if (it->second !=
seq)
1966 nUnlLedgerSeq.
erase(it);
1968 return nUnlLedgerSeq.
size() == 0;
1975 for (
auto i = txSet->begin(); i != txSet->end(); ++i)
1989 for (
int i = 0; i < n; ++i)
1992 Slice s(data.data(), ss);
2001 auto fill = [&](
auto& obj) {
2002 obj.setFieldU8(sfUNLModifyDisabling, disabling ? 1 : 0);
2003 obj.setFieldU32(sfLedgerSequence,
seq);
2004 obj.setFieldVL(sfUNLModifyValidator, txKey);
2006 return STTx(ttUNL_MODIFY, fill);
testcase_t testcase
Memberspace for declaring test cases.
virtual Config & config()=0
virtual Overlay & overlay()=0
virtual TimeKeeper & timeKeeper()=0
virtual NetworkOPs & getOPs()=0
virtual ValidatorList & validators()=0
virtual Family & getNodeFamily()=0
virtual HashRouter & getHashRouter()=0
Manager to create NegativeUNL votes.
static constexpr size_t negativeUNLHighWaterMark
An unreliable validator must have more than negativeUNLHighWaterMark validations in the last flag led...
NodeID choose(uint256 const &randomPadData, std::vector< NodeID > const &candidates)
Pick one candidate from a vector of candidates.
std::optional< hash_map< NodeID, std::uint32_t > > buildScoreTable(std::shared_ptr< Ledger const > const &prevLedger, hash_set< NodeID > const &unl, RCLValidations &validations)
Build a reliability measurement score table of validators' validation messages in the last flag ledge...
void purgeNewValidators(LedgerIndex seq)
Purge validators that are not new anymore.
Candidates const findAllCandidates(hash_set< NodeID > const &unl, hash_set< NodeID > const &negUnl, hash_map< NodeID, std::uint32_t > const &scoreTable)
Process the score table and find all disabling and re-enabling candidates.
static constexpr size_t newValidatorDisableSkip
We don't want to disable new validators immediately after adding them.
static constexpr size_t negativeUNLLowWaterMark
A validator is considered unreliable if its validations is less than negativeUNLLowWaterMark in the l...
void doVoting(std::shared_ptr< Ledger const > const &prevLedger, hash_set< PublicKey > const &unlKeys, RCLValidations &validations, std::shared_ptr< SHAMap > const &initialSet)
Cast our local vote on the NegativeUNL candidates.
hash_map< NodeID, LedgerIndex > newValidators_
void newValidators(LedgerIndex seq, hash_set< NodeID > const &nowTrusted)
Notify NegativeUNLVote that new validators are added.
void addTx(LedgerIndex seq, PublicKey const &vp, NegativeUNLModify modify, std::shared_ptr< SHAMap > const &initialSet)
Add a ttUNL_MODIFY Tx to the transaction set.
static constexpr size_t negativeUNLMinLocalValsToVote
The minimum number of validations of the local node for it to participate in the voting.
Writable ledger view that accumulates state and tx changes.
void apply(TxsRawView &to) const
Apply changes.
Wrapper over STValidation for generic Validation code.
An immutable linear range of bytes.
time_point now() const override
Returns the current time, using the server's clock.
time_point closeTime() const
Returns the predicted close time, in network time.
ValStatus add(NodeID const &nodeID, Validation const &val)
Add a new validation.
time_point now() const override
Returns the current time.
void testNegativeUNLNoAmendment()
void run() override
Runs the suite.
void run() override
Runs the suite.
void testFilterValidations()
void run() override
Runs the suite.
Test the private member functions of NegativeUNLVote.
void testPickOneCandidate()
void testFindAllCandidates()
void testBuildScoreTableSpecialCases()
void run() override
Runs the suite.
bool checkCandidateSizes(NegativeUNLVote &vote, hash_set< NodeID > const &unl, hash_set< NodeID > const &negUnl, hash_map< NodeID, std::uint32_t > const &scoreTable, std::size_t numDisable, std::size_t numReEnable)
Find all candidates and check if the number of candidates meets expectation.
void testFindAllCandidatesCombination()
void run() override
Runs the suite.
void run() override
Runs the suite.
void run() override
Runs the suite.
void run() override
Runs the suite.
Rest the build score table function of NegativeUNLVote.
void testBuildScoreTableCombination()
void run() override
Runs the suite.
void run() override
Runs the suite.
void testNegativeUNL()
Test filling and applying ttUNL_MODIFY Tx, as well as ledger update:
A transaction testing environment.
beast::Journal const journal
ManualTimeKeeper & timeKeeper()
T emplace_back(T... args)
Keylet const & negativeUNL() noexcept
The (fixed) index of the object containing the ledger negativeUNL.
FeatureBitset testable_amendments()
std::size_t countTx(std::shared_ptr< SHAMap > const &txSet)
Count the number of Tx in a TxSet.
bool negUnlSizeTest(std::shared_ptr< Ledger const > const &l, size_t size, bool hasToDisable, bool hasToReEnable)
Test the size of the negative UNL in a ledger, also test if the ledger has ToDisalbe and/or ToReEnabl...
std::vector< PublicKey > createPublicKeys(std::size_t n)
Create fake public keys.
STTx createTx(bool disabling, LedgerIndex seq, PublicKey const &txKey)
Create ttUNL_MODIFY Tx.
bool applyAndTestResult(jtx::Env &env, OpenView &view, STTx const &tx, bool pass)
Try to apply a ttUNL_MODIFY Tx, and test the apply result.
bool voteAndCheck(NetworkHistory &history, NodeID const &myId, std::size_t expect, PreVote const &pre=defaultPreVote)
Create a NegativeUNLVote object.
bool VerifyPubKeyAndSeq(std::shared_ptr< Ledger const > const &l, hash_map< PublicKey, std::uint32_t > nUnlLedgerSeq)
Verify the content of negative UNL entries (public key and ledger sequence) of a ledger.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
std::uint32_t LedgerIndex
A ledger index.
base_uint< 160, detail::NodeIDTag > NodeID
NodeID is a 160-bit hash representing one node.
PublicKey derivePublicKey(KeyType type, SecretKey const &sk)
Derive the public key from a secret key.
std::optional< KeyType > publicKeyType(Slice const &slice)
Returns the type of public key.
std::enable_if_t< std::is_same< T, char >::value||std::is_same< T, unsigned char >::value, Slice > makeSlice(std::array< T, N > const &a)
SecretKey randomSecretKey()
Create a secret key using secure random numbers.
NodeID calcNodeID(PublicKey const &)
Calculate the 160-bit node ID from a node public key.
ApplyResult apply(Application &app, OpenView &view, STTx const &tx, ApplyFlags flags, beast::Journal journal)
Apply a transaction to an OpenView.
create_genesis_t const create_genesis
std::pair< PublicKey, SecretKey > randomKeyPair(KeyType type)
Create a key pair using secure random numbers.
Only reasonable parameters can be honored, e.g cannot hasToReEnable when nUNLSize == 0.
std::optional< int > numLedgers
if not specified, the number of ledgers in the history is calculated from negUNLSize,...
Utility class for creating validators and ledger history.
std::shared_ptr< Ledger const > lastLedger() const
void walkHistoryAndAddValidations(NeedValidation &&needVal)
Walk the ledger history and create validation messages for the ledgers.
NetworkHistory(beast::unit_test::suite &suite, Parameter const &p)
std::vector< NodeID > UNLNodeIDs
std::shared_ptr< STValidation > createSTVal(std::shared_ptr< Ledger const > const &ledger, NodeID const &v)
Create a validation.
hash_set< NodeID > UNLNodeIDSet
std::vector< PublicKey > UNLKeys
bool createLedgerHistory()
create ledger history and apply needed ttUNL_MODIFY tx at flag ledgers
RCLValidations & validations
hash_set< PublicKey > UNLKeySet
Set the sequence number on a JTx.