3#include <xrpld/app/consensus/RCLValidations.h>
4#include <xrpld/app/ledger/Ledger.h>
5#include <xrpld/app/misc/NegativeUNLVote.h>
6#include <xrpld/app/misc/ValidatorList.h>
7#include <xrpld/app/tx/apply.h>
9#include <xrpl/beast/unit_test.h>
10#include <xrpl/ledger/View.h>
68 hash_map<PublicKey, std::uint32_t> nUnlLedgerSeq);
209 testcase(
"Create UNLModify Tx and apply to ledgers");
219 BEAST_EXPECT(l->rules().enabled(featureNegativeUNL));
230 auto txDisable_0 =
createTx(
true, l->seq(), publicKeys[0]);
231 auto txReEnable_1 =
createTx(
false, l->seq(), publicKeys[1]);
243 for (
auto i = 0; i < 256 - 2; ++i)
248 BEAST_EXPECT(l->isFlagLedger());
249 l->updateNegativeUNL();
251 auto txDisable_0 =
createTx(
true, l->seq(), publicKeys[0]);
252 auto txDisable_1 =
createTx(
true, l->seq(), publicKeys[1]);
253 auto txReEnable_2 =
createTx(
false, l->seq(), publicKeys[2]);
263 BEAST_EXPECT(good_size);
266 BEAST_EXPECT(l->validatorToDisable() == publicKeys[0]);
268 uint256 txID = txDisable_0.getTransactionID();
269 BEAST_EXPECT(l->txExists(txID));
275 for (
auto i = 0; i < 256; ++i)
278 BEAST_EXPECT(good_size);
280 BEAST_EXPECT(l->validatorToDisable() == publicKeys[0]);
284 BEAST_EXPECT(l->isFlagLedger());
285 l->updateNegativeUNL();
290 BEAST_EXPECT(good_size);
293 BEAST_EXPECT(*(l->negativeUNL().begin()) == publicKeys[0]);
294 nUnlLedgerSeq.
emplace(publicKeys[0], l->seq());
297 auto txDisable_0 =
createTx(
true, l->seq(), publicKeys[0]);
298 auto txDisable_1 =
createTx(
true, l->seq(), publicKeys[1]);
299 auto txReEnable_0 =
createTx(
false, l->seq(), publicKeys[0]);
300 auto txReEnable_1 =
createTx(
false, l->seq(), publicKeys[1]);
301 auto txReEnable_2 =
createTx(
false, l->seq(), publicKeys[2]);
311 BEAST_EXPECT(good_size);
314 BEAST_EXPECT(l->negativeUNL().count(publicKeys[0]));
315 BEAST_EXPECT(l->validatorToDisable() == publicKeys[1]);
316 BEAST_EXPECT(l->validatorToReEnable() == publicKeys[0]);
324 for (
auto i = 0; i < 256; ++i)
327 BEAST_EXPECT(good_size);
330 BEAST_EXPECT(l->negativeUNL().count(publicKeys[0]));
331 BEAST_EXPECT(l->validatorToDisable() == publicKeys[1]);
332 BEAST_EXPECT(l->validatorToReEnable() == publicKeys[0]);
337 BEAST_EXPECT(l->isFlagLedger());
338 l->updateNegativeUNL();
343 BEAST_EXPECT(good_size);
346 BEAST_EXPECT(l->negativeUNL().count(publicKeys[1]));
349 auto txDisable_0 =
createTx(
true, l->seq(), publicKeys[0]);
355 BEAST_EXPECT(good_size);
358 BEAST_EXPECT(l->negativeUNL().count(publicKeys[1]));
359 BEAST_EXPECT(l->validatorToDisable() == publicKeys[0]);
360 nUnlLedgerSeq.
emplace(publicKeys[1], l->seq());
361 nUnlLedgerSeq.
erase(publicKeys[0]);
368 for (
auto i = 0; i < 256; ++i)
371 BEAST_EXPECT(good_size);
374 BEAST_EXPECT(l->negativeUNL().count(publicKeys[1]));
375 BEAST_EXPECT(l->validatorToDisable() == publicKeys[0]);
380 BEAST_EXPECT(l->isFlagLedger());
381 l->updateNegativeUNL();
386 BEAST_EXPECT(good_size);
389 BEAST_EXPECT(l->negativeUNL().count(publicKeys[0]));
390 BEAST_EXPECT(l->negativeUNL().count(publicKeys[1]));
391 nUnlLedgerSeq.
emplace(publicKeys[0], l->seq());
395 auto txDisable_0 =
createTx(
true, l->seq(), publicKeys[0]);
396 auto txReEnable_0 =
createTx(
false, l->seq(), publicKeys[0]);
397 auto txReEnable_1 =
createTx(
false, l->seq(), publicKeys[1]);
405 BEAST_EXPECT(good_size);
408 BEAST_EXPECT(l->negativeUNL().count(publicKeys[0]));
409 BEAST_EXPECT(l->negativeUNL().count(publicKeys[1]));
410 BEAST_EXPECT(l->validatorToReEnable() == publicKeys[0]);
417 for (
auto i = 0; i < 256; ++i)
420 BEAST_EXPECT(good_size);
423 BEAST_EXPECT(l->negativeUNL().count(publicKeys[0]));
424 BEAST_EXPECT(l->negativeUNL().count(publicKeys[1]));
425 BEAST_EXPECT(l->validatorToReEnable() == publicKeys[0]);
430 BEAST_EXPECT(l->isFlagLedger());
431 l->updateNegativeUNL();
436 BEAST_EXPECT(good_size);
439 BEAST_EXPECT(l->negativeUNL().count(publicKeys[1]));
440 nUnlLedgerSeq.
erase(publicKeys[0]);
444 auto txReEnable_1 =
createTx(
false, l->seq(), publicKeys[1]);
450 BEAST_EXPECT(good_size);
453 BEAST_EXPECT(l->negativeUNL().count(publicKeys[1]));
454 BEAST_EXPECT(l->validatorToReEnable() == publicKeys[1]);
461 for (
auto i = 0; i < 256; ++i)
464 BEAST_EXPECT(good_size);
467 BEAST_EXPECT(l->negativeUNL().count(publicKeys[1]));
468 BEAST_EXPECT(l->validatorToReEnable() == publicKeys[1]);
473 BEAST_EXPECT(l->isFlagLedger());
474 l->updateNegativeUNL();
482 for (
auto i = 0; i < 256; ++i)
488 BEAST_EXPECT(l->isFlagLedger());
489 l->updateNegativeUNL();
508 testcase(
"No negative UNL amendment");
518 BEAST_EXPECT(!l->rules().enabled(featureNegativeUNL));
521 for (
auto i = 0; i < 256 - 1; ++i)
526 BEAST_EXPECT(l->seq() == 256);
527 auto txDisable_0 =
createTx(
true, l->seq(), publicKeys[0]);
613 if (l->isFlagLedger())
615 l->updateNegativeUNL();
664 v.setFieldH256(sfLedgerHash, ledger->info().hash);
665 v.setFieldU32(sfLedgerSequence, ledger->seq());
666 v.setFlag(vfFullValidation);
677 template <
class NeedVal
idation>
729template <
typename PreVote = decltype(defaultPreVote)>
743 return countTx(txSet) == expect;
768 BEAST_EXPECT(
countTx(txSet) == 0);
770 BEAST_EXPECT(
countTx(txSet) == 1);
772 BEAST_EXPECT(
countTx(txSet) == 2);
792 BEAST_EXPECT(vote.
choose(pad_0, candidates) == n_1);
793 BEAST_EXPECT(vote.
choose(pad_f, candidates) == n_1);
794 candidates.emplace_back(2);
795 BEAST_EXPECT(vote.
choose(pad_0, candidates) == n_1);
796 BEAST_EXPECT(vote.
choose(pad_f, candidates) == n_2);
797 candidates.emplace_back(3);
798 BEAST_EXPECT(vote.
choose(pad_0, candidates) == n_1);
799 BEAST_EXPECT(vote.
choose(pad_f, candidates) == n_3);
873 BEAST_EXPECT(wrongChainSuccess);
894 for (
auto& l : wrongChain)
910 BEAST_EXPECT(scoreTable);
913 for (
auto const& [n, score] : *scoreTable)
916 BEAST_EXPECT(score == 256);
918 BEAST_EXPECT(score == 0);
946 BEAST_EXPECT(scoreTable);
949 for (
auto const& [_, score] : *scoreTable)
952 BEAST_EXPECT(score == 256);
980 auto [disableCandidates, reEnableCandidates] =
982 bool rightDisable = disableCandidates.size() == numDisable;
983 bool rightReEnable = reEnableCandidates.size() == numReEnable;
984 return rightDisable && rightReEnable;
1023 vote, history.
UNLNodeIDSet, negUnl_012, goodScoreTable, 0, 3));
1031 vote, history.
UNLNodeIDSet, negUnl_012, scoreTable, 35 - 3, 0));
1039 vote, history.
UNLNodeIDSet, negUnl_012, scoreTable, 0, 0));
1044 auto scoreTable = goodScoreTable;
1045 scoreTable[*negUnl_012.
begin()] =
1048 vote, history.
UNLNodeIDSet, negUnl_012, scoreTable, 0, 2));
1053 auto scoreTable = goodScoreTable;
1059 vote, history.
UNLNodeIDSet, negUnl_012, scoreTable, 2, 3));
1069 vote, UNL_temp, negUnl_012, goodScoreTable, 0, 3));
1074 auto scoreTable = goodScoreTable;
1083 vote, UNL_temp, negUnl_012, scoreTable, 0, 2));
1097 auto scoreTable = goodScoreTable;
1103 negUnl_temp.
insert(new_1);
1104 negUnl_temp.
insert(new_2);
1106 vote, UNL_temp, negUnl_temp, scoreTable, 0, 3 + 2));
1110 auto scoreTable = goodScoreTable;
1111 scoreTable[new_1] = 0;
1112 scoreTable[new_2] = 0;
1114 vote, UNL_temp, negUnl_012, scoreTable, 0, 3));
1120 auto scoreTable = goodScoreTable;
1121 scoreTable[new_1] = 0;
1122 scoreTable[new_2] = 0;
1124 vote, UNL_temp, negUnl_012, scoreTable, 2, 3));
1132 testcase(
"Find All Candidates Combination");
1168 auto fillScoreTable =
1177 for (
auto const& k : keys)
1180 unl.emplace(nodeIDs.
back());
1181 scoreTable[nodeIDs.
back()] = score;
1184 negUnl.insert(nodeIDs[i]);
1187 for (
auto us : unlSizes)
1189 for (
auto np : nUnlPercent)
1191 for (
auto score : scores)
1197 us, us * np / 100, score, unl, negUnl, scoreTable);
1198 BEAST_EXPECT(unl.
size() == us);
1199 BEAST_EXPECT(negUnl.
size() == us * np / 100);
1200 BEAST_EXPECT(scoreTable.
size() == us);
1209 toDisable_expect = us;
1217 toReEnable_expect = us * np / 100;
1225 toReEnable_expect = us;
1234 toReEnable_expect));
1241 auto fillScoreTable =
1250 for (
auto const& k : keys)
1253 unl.emplace(nodeIDs.
back());
1257 for (
auto score : scores)
1259 scoreTable[nodeIDs[nIdx++]] = score;
1260 scoreTable[nodeIDs[nIdx++]] = score;
1262 for (; nIdx < unl_size;)
1264 scoreTable[nodeIDs[nIdx++]] = scores.
back();
1267 if (nUnl_percent == 100)
1271 else if (nUnl_percent == 50)
1274 negUnl.insert(nodeIDs[i]);
1278 for (
auto us : unlSizes)
1280 for (
auto np : nUnlPercent)
1286 fillScoreTable(us, np, unl, negUnl, scoreTable);
1287 BEAST_EXPECT(unl.
size() == us);
1288 BEAST_EXPECT(negUnl.
size() == us * np / 100);
1289 BEAST_EXPECT(scoreTable.
size() == us);
1295 toDisable_expect = 4;
1299 toReEnable_expect = negUnl.
size() - 6;
1303 toReEnable_expect = negUnl.
size() - 12;
1311 toReEnable_expect));
1399 testcase(
"Build Score Table Combination");
1408 {{{0, 0, 0}}, {{50, 50, 50}}, {{100, 100, 100}}, {{0, 50, 100}}}};
1410 for (
auto unlSize : unlSizes)
1415 *
this, {unlSize, 0,
false,
false, 256 + 2}};
1432 scorePattern[sp][k] == 50 && l->seq() % 2 == 0;
1433 bool add_100 = scorePattern[sp][k] == 100;
1434 bool add_me = history.
UNLNodeIDs[idx] == myId;
1435 return add_50 || add_100 || add_me;
1443 BEAST_EXPECT(scoreTable);
1450 return score == 256;
1451 if (scorePattern[sp][k] == 0)
1453 if (scorePattern[sp][k] == 50)
1454 return score == 256 / 2;
1455 if (scorePattern[sp][k] == 100)
1456 return score == 256;
1462 BEAST_EXPECT(checkScores(
1467 BEAST_EXPECT(checkScores(
1470 for (; i < unlSize; ++i)
1472 BEAST_EXPECT(checkScores(
1702 history.UNLKeySet.erase(history.UNLKeys[0]);
1703 history.UNLKeySet.erase(history.UNLKeys[1]);
1739 randomKeyPair(KeyType::ed25519).first;
1741 randomKeyPair(KeyType::ed25519).first;
1742 history.UNLKeySet.insert(extra_key_1);
1743 history.UNLKeySet.insert(extra_key_2);
1744 hash_set<NodeID> nowTrusted;
1745 nowTrusted.insert(calcNodeID(extra_key_1));
1746 nowTrusted.insert(calcNodeID(extra_key_2));
1748 history.lastLedger()->seq(), nowTrusted);
1775 randomKeyPair(KeyType::ed25519).first;
1777 randomKeyPair(KeyType::ed25519).first;
1778 history.UNLKeySet.insert(extra_key_1);
1779 history.UNLKeySet.insert(extra_key_2);
1780 hash_set<NodeID> nowTrusted;
1781 nowTrusted.insert(calcNodeID(extra_key_1));
1782 nowTrusted.insert(calcNodeID(extra_key_2));
1783 vote.newValidators(256, nowTrusted);
1816 v.setFieldH256(sfLedgerHash, l->info().hash);
1817 v.setFieldU32(sfLedgerSequence, l->seq());
1818 v.setFlag(vfFullValidation);
1829 for (
int i = 0; i < numNodes; ++i)
1837 nUnlKeys.
insert(keyPair.first);
1843 auto& local = *nUnlKeys.
begin();
1845 validators.load(local, cfgKeys, cfgPublishers);
1846 validators.updateTrusted(
1852 BEAST_EXPECT(validators.getTrustedMasterKeys().size() == numNodes);
1853 validators.setNegativeUNL(nUnlKeys);
1854 BEAST_EXPECT(validators.getNegativeUNL().size() == negUnlSize);
1857 BEAST_EXPECT(vals.
size() == numNodes);
1858 vals = validators.negativeUNLFilter(std::move(vals));
1859 BEAST_EXPECT(vals.
size() == numNodes - negUnlSize);
1869BEAST_DEFINE_TESTSUITE(NegativeUNL, consensus,
ripple);
1870BEAST_DEFINE_TESTSUITE(NegativeUNLNoAmendment, consensus,
ripple);
1872BEAST_DEFINE_TESTSUITE(NegativeUNLVoteInternal, consensus,
ripple);
1873BEAST_DEFINE_TESTSUITE_MANUAL(NegativeUNLVoteScoreTable, consensus,
ripple);
1874BEAST_DEFINE_TESTSUITE_PRIO(NegativeUNLVoteGoodScore, consensus,
ripple, 1);
1875BEAST_DEFINE_TESTSUITE(NegativeUNLVoteOffline, consensus,
ripple);
1876BEAST_DEFINE_TESTSUITE(NegativeUNLVoteMaxListed, consensus,
ripple);
1877BEAST_DEFINE_TESTSUITE_PRIO(
1878 NegativeUNLVoteRetiredValidator,
1882BEAST_DEFINE_TESTSUITE(NegativeUNLVoteNewValidator, consensus,
ripple);
1883BEAST_DEFINE_TESTSUITE(NegativeUNLVoteFilterValidations, consensus,
ripple);
1895 bool sameSize = l->negativeUNL().size() == size;
1896 bool sameToDisable =
1897 (l->validatorToDisable() !=
std::nullopt) == hasToDisable;
1898 bool sameToReEnable =
1899 (l->validatorToReEnable() !=
std::nullopt) == hasToReEnable;
1901 return sameSize && sameToDisable && sameToReEnable;
1923 if (!sle->isFieldPresent(sfDisabledValidators))
1926 auto const& nUnlData = sle->getFieldArray(sfDisabledValidators);
1927 if (nUnlData.size() != nUnlLedgerSeq.
size())
1930 for (
auto const& n : nUnlData)
1932 if (!n.isFieldPresent(sfFirstLedgerSequence) ||
1933 !n.isFieldPresent(sfPublicKey))
1936 auto seq = n.getFieldU32(sfFirstLedgerSequence);
1937 auto d = n.getFieldVL(sfPublicKey);
1942 auto it = nUnlLedgerSeq.
find(pk);
1943 if (it == nUnlLedgerSeq.
end())
1945 if (it->second !=
seq)
1947 nUnlLedgerSeq.
erase(it);
1949 return nUnlLedgerSeq.
size() == 0;
1956 for (
auto i = txSet->begin(); i != txSet->end(); ++i)
1970 for (
int i = 0; i < n; ++i)
1982 auto fill = [&](
auto& obj) {
1983 obj.setFieldU8(sfUNLModifyDisabling, disabling ? 1 : 0);
1984 obj.setFieldU32(sfLedgerSequence,
seq);
1985 obj.setFieldVL(sfUNLModifyValidator, txKey);
1987 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.
auto const data
General field definitions, or fields used in multiple transaction namespaces.
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.